<SECTION=Programs>
<program>
program test; 		-- 
	use string_utility_pak;
	print(""," ");
end test;
<HELP>
SETL programs have the form 

	program prog_name; 
		use package_name,class_name,.;
		
		statements

		procedure name(parameter,parameter,); 		
			more_statements
		end name;
	
		procedure other_name(parameter,parameter,); 		
			other_statements
		end name;

	end prog_name;

The 'use' clause and subprocedures shown can be omitted. 'var' and 'const' statements declaring global variables can appear at the start of the program, after the 'use' clause.

Execution of a program begins with its first statement.  

<use>
	use xxx,xxx;

<HELP>
Use  clauses can appear at the start of programs, package bodies, and class bodies. They list the other packages and classes which these programs, packages, and classes wish to import. Library hierarchies can be built up by having higher level packages and classes import lower level packages and classes. Packages and classes can even 'use' (i.e. import) each other circularly, provided that their header blocks are compiled previous to their bodies. See the main SETL manual for an account of the name visbility rules which apply to names in imported packages.

<const>
	const xxx := xxx, xxx := xxx;

<HELP>
const  clauses can appear at the start of programs, procedures, package headers, class headers, package bodies, and class bodies. They serve to define the value of constants througout the scopes in which they are visible.

const clauses which appear in package or class headers make the named constants global in all programs, packages and classes which import them.
 
<var>
	var xxx , xxx := xxx;

<HELP>
var clauses can appear at the start of programs, procedures, package headers, class headers, package bodies, and class bodies. They define the scopes in which the variable names they list are visible.

var clauses which appear in package or class headers make the named variables global in all programs, packages and classes which import them.

var clauses which appear in class bodies have an important additional function: they define the 'instance variables' of the class; a private copy of each of these variables is created for each instance of the class. variables of which just one copy acessible to all such instances should be declared as 'class var' rather than 'var'.

<procedure>
procedure xxx(); 		-- 

	return zzz;
end xxx;

<HELP>
Procedure blocks have the form 

	procedure name(parameter,parameter,); 		
		statements
	end name;

The enclosed statements are executed when the procedure is invoked. The formal parameters listed must all be distinct. If the procedure is to modify one or more of its parameters when called, those parameters must be prefixed by one of the qualifiers 

Variable and parameter names appearing in a procedure are local to the procedure 
Procedures can contain declarations of their local variables, of constants used in the procedure, and can contin the bodies of nested subprocedures.

Return statements can be used within procedures. They have the form 

	return expn;				or 			return;

the latter equivalent to 'return OM;'

<return>
return zzz;

<HELP>
Return statements can be used within procedures. They have the form 

	return expn;				or 			return;

the latter equivalent to 'return OM;'

<if>
if xxx then

end if;

<HELP>
The 'if' statement can have one of several forms. Its simplest form is

		if condition then
			statements
		end if;

This executes the enclosed 'statements' if the 'condition' (whose value must be true or false)
has the value 'true'. The more elaborate form 

		if condition then
			statements
		else
			other_statements
		end if;

executes the enclosed 'other_statements' if the 'condition' has the value 'false'.

The still more elaborate form 

		if condition then
			statements
		elseif other_condition  then
			other_statements		
		else
			still_other_statements		
		end if;
		
tests a second 'other_condition' if 'condition' fails. This can have any number of 
'elseif' clauses, and can omit the 'else' clause.

<ifelse>
if xxx then

else

end if;

<HELP>
The 'if' statement can have one of several forms. Its simplest form is

		if condition then
			statements
		end if;

This executes the enclosed 'statements' if the 'condition' (whose value must be true or false)
has the value 'true'. The more elaborate form 

		if condition then
			statements
		else
			other_statements
		end if;

executes the enclosed 'other_statements' if the 'condition' has the value 'false'.

The still more elaborate form 

		if condition then
			statements
		elseif other_condition  then
			other_statements		
		else
			still_other_statements		
		end if;
		
tests a second 'other_condition' if 'condition' fails. This can have any number of 
'elseif' clauses, and can omit the 'else' clause.

<ifelseif>
if xxx then

elseif xxx  then

else

end if;

<HELP>
The 'if' statement can have one of several forms. Its simplest form is

		if condition then
			statements
		end if;

This executes the enclosed 'statements' if the 'condition' (whose value must be true or false)
has the value 'true'. The more elaborate form 

		if condition then
			statements
		else
			other_statements
		end if;

executes the enclosed 'other_statements' if the 'condition' has the value 'false'.

The still more elaborate form 

		if condition then
			statements
		elseif other_condition  then
			other_statements		
		else
			still_other_statements		
		end if;
		
tests a second 'other_condition' if 'condition' fails. This can have any number of 
'elseif' clauses, and can omit the 'else' clause.

<while>
while xxx loop	--

end loop;

<HELP>
The 'while' statement 

	while condition loop
		statements
	end loop;

executes the enclosed 'statements' as long as 'condition' (which is tested at the start of each iteration) is true.

<until>
until xxx loop	--

end loop;

<HELP>
The 'until' statement 

	until condition loop
		statements
	end loop;

executes the enclosed 'statements' until 'condition' (which is tested at the start of each iteration) becomes false.

<forin>
for xxx in xxx | xxx loop	--

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...
<for=f()>
for xxx = xxx(xxx) | xxx loop	--

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...

<for=f{}>
for xxx = xxx{xxx} | xxx loop	--

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...

end loop;

<continue;>
continue;

<HELP>
The statements

		continue; 			and 			exit;
		
are used within SETL loops to proceed immediately to the next iteration, and to exit the loop, respectively. 

<exit;>
exit;

<HELP>
The statements

		continue; 			and 			exit;
		
are used within SETL loops to proceed immediately to the next iteration, and to exit the loop, respectively. 

<case>
case xxx 		-- 

	when xxx =>	-- 

	when xxx =>	-- 

	otherwise =>	-- 
	
end case;

<HELP>
The 'case' statement can have one of two main forms. The first form is

	case expression 		
	
		when const_val, =>	
				statements
		when other_const_val, =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'expression' is evaluated and compared to the const_vals which appear in the
when 'const_val, =>' clauses (These must all be distinct.) If any equality is
found, the corresponding 'statements', but only these, are executed. If no equality is
found, the 'still_other_statements' following the 'otherwise =>' clause are executed,
provided that this clause has not been omitted, if it can be.

The second form of 'case' statement is

	case 		
	
		when boolean_expression =>	
				statements
		when other_boolean_expression =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'boolean_expressions' in this statement are evaluated until one of them is found to be true, and then the corresponding 'statements', but only these, are executed. If none of these 'boolean_expressions' is found  to be true, the 'still_other_statements' following the 'otherwise =>' clause are executed, provided that this clause has not been omitted, as it can be.

<case(form2)>
case  		-- 

	when xxx =>	-- 

	when xxx =>	-- 

	otherwise =>	-- 
	
end case;

<HELP>
The 'case' statement can have one of two main forms. The first form is

	case expression 		
	
		when const_val, =>	
				statements
		when other_const_val, =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'expression' is evaluated and compared to the const_vals which appear in the
when 'const_val, =>' clauses (These must all be distinct.) If any equality is
found, the corresponding 'statements', but only these, are executed. If no equality is
found, the 'still_other_statements' following the 'otherwise =>' clause are executed,
provided that this clause has not been omitted, if it can be.

The second form of 'case' statement is

	case 		
	
		when boolean_expression =>	
				statements
		when other_boolean_expression =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'boolean_expressions' in this statement are evaluated until one of them is found to be true, and then the corresponding 'statements', but only these, are executed. If none of these 'boolean_expressions' is found  to be true, the 'still_other_statements' following the 'otherwise =>' clause are executed, provided that this clause has not been omitted, as it can be.

<{ in }>
{xxx: xxx in xxx | }
<HELP>
Setformers like {n * n: n in s | n /= 0} form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write {n in s | n /= 0} or {n * n: n in s}.

<{ = f()}>
{xxx: xxx = xxx(xxx) | }
<HELP>
Setformers like {n * n: n in s | n /= 0} form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write {n in s | n /= 0} or {n * n: n in s}.

<{ = f{}}>
{xxx: xxx = xxx{xxx} | }
<HELP>
Setformers like {n * n: n in s | n /= 0} form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write {n in s | n /= 0} or {n * n: n in s}.

<[ in ]>
[xxx: xxx in xxx | ]
<HELP>
Tuple formers like [n * n: n in s | n /= 0] form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write [n in s | n /= 0] or [n * n: n in s].

<[ = f()]>
[xxx: xxx = xxx{xxx} | ]
<HELP>
Tuple formers like [n * n: n in s | n /= 0] form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write [n in s | n /= 0] or [n * n: n in s].

<[ = f{}]>
[xxx: xxx = xxx{xxx} | ]
<HELP>
Tuple formers like [n * n: n in s | n /= 0] form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write [n in s | n /= 0] or [n * n: n in s].

<existsin>
(exists xxx in xxx | (xxx))
<HELP>
Existential quantifiers  like 

	exists n in s | n /= 0

test for the existence of the element which they describe in a notation close to that of standard mathematics, and if any such exists one is returned as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such existentials.

<exists=f()>
(exists xxx = xxx(xxx) | (xxx))
<HELP>
Existential quantifiers  like 

	exists n in s | n /= 0

test for the existence of the element which they describe in a notation close to that of standard mathematics, and if any such exists one is returned as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such existentials.

<exists=f{}>
(exists xxx = xxx{xxx} | (xxx))
<HELP>
Existential quantifiers  like 

	exists n in s | n /= 0

test for the existence of the element which they describe in a notation close to that of standard mathematics, and if any such exists one is returned as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such existentials.

<forallin>
(forall xxx in xxx | (xxx))
<HELP>
Universal quantifiers  like 

	for n in s | n /= 0

assert the truth of a condition, using a notation close to that of standard mathematics. If this is verifieed they return 'true'.  If not, they return 'false', and also return a counterexample as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such quantifiers.

<forall=f()>
(forall xxx = xxx(xxx) | (xxx))
<HELP>
Universal quantifiers  like 

	for n in s | n /= 0

assert the truth of a condition, using a notation close to that of standard mathematics. If this is verifieed they return 'true'.  If not, they return 'false', and also return a counterexample as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such quantifiers.

<forall=f{}>
(forall xxx = xxx{xxx} | (xxx))
<HELP>
Universal quantifiers  like 

	for n in s | n /= 0

assert the truth of a condition, using a notation close to that of standard mathematics. If this is verifieed they return 'true'.  If not, they return 'false', and also return a counterexample as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such quantifiers.

<lambda>
	procedure binder(param);		-- this returns a 'closure'
		return lambda(); return param; end lambda;
					-- this binds param into the parameterless function returned
	end binder;	

<HELP>
lambda blocks have the form 

	lambda(parameter,parameter,..); 		
		statements..
	end lambda;

They are nearly identical with procedure blocks, but have only parameters, not any name, since they are used to form 'anonymous' procedures, typically in contexts like 

	x := lambda(parameter,parameter,..); 		
		statements..
	end lambda;

which forms a procedure and assigns it to the value x. A simple example is 

		procedure bind_summand(n);
			return lambda(y); return y + n; end lambda;
		end bind_summand;
		
which when called forms a procedure into which the parameter value in is 'bound', so that for example the code

	p := bind_summand(222000); print(p(999));

prints the value 222999;

As this example shows, return statements can be used within lambda blocks. They have the form 

	return expn;				or 			return;

the latter equivalent to 'return OM;'

<null;>
null;

<HELP>
null statements  do nothing. They are used as syntactic filler where required, e.g. to be put in otherwise empty loops as surrogates for code still to be written;
<comments>
		--
		--

<HELP>
SETL comments are introduced by unquoted double minus signs, and run to the end of the line on which these signs appear. For example

	print("-- something");		-- what appears to the left is code, but this is just a comment
<print>
print(" ",xxx," ",xxx); 

<HELP>
print statements convert their sucessive arguments to strings and print them to SETL's standard output file or console. A newline is written after the final character printed by each print statement. To suppress this action, use 'nprint' instead.

<open>
xxx := open(xxx,"random");		-- or "text-out", "text-in", "binary-out", "binary-in", 

<HELP>
The statement 

	file_handle := open(file_name,"random");

converts the string name of a file into the 'handle' needed by other operations to reference the file. Other possibilities are 

	open(file_name,"text-out");
	open(file_name,"text-in");
	open(file_name,"binary-out");
	open(file_name,"binary-in");

Files can be opened only once, and must exist to be opened in any mode but "text-out" or "binary-out". The mode in which a file is be opened constrains the operations which can be applied to it, e.g. a file opened as "text-in" or  "binary-in" cannot be written

Both the "text-out" and "binary-out" modes of file acess begin by erasing the file being opened; newly opened files are always positioned at their start.
<close>
close(xxx);

<HELP>
close(file_handle); closes the file referenced by file_handle, allowing it to be re-opened subsequently.
<fexists()>
fexists(xxx);
<HELP>
fexists(file_name) returns 'true' if the naed file exists, 'false' otherwise.
<fsize()>
fsize(xxx)
<HELP>
fsize(file_handle) returns the length in bytes of the file referenced by file_handle.
<nprint>
nprint(xxx," ",xxx);  

<HELP>
nprint statements convert their sucessive arguments to strings and print them to SETL's standard output file or console. No newline is written after the final character printed.
<read>
read(xxx);  

<HELP>
read(x,y); statements read one complete SETL object from the standard input file or console for each of its (variable number of) arguments, and assigns it to this argument. It generates an error it it encounters a quantity which is not the legal print form of a SETL object.   

<reads>
reads(xxx,xxx,xxx); 
<HELP>
reads(stg,x,y); statements read one complete SETL object from the string s for each of its (variable number of) arguments, and assigns it to this argument. It generates an error it it encounters a quantity which is not the legal print form of a SETL object. The porion read is removed from s.   

<get>
get(xxx,xxx);
<HELP>
get(x,y); statements read one line from the standard input file or console for each of their (variable number of) arguments, and assigns the string read to this argument.

<geta>
geta(xxx,xxx,xxx);

<HELP>
geta(file_handle,x,y); statements read one line from the file referenced by file_handle for each of their (variable number of) arguments, and assigns the string read to this argument.

<gets>
gets(xxx,xxx,xxx,xxx);

<HELP>
gets(file_handle,start,n,x); statements read a string of length n from the file referenced by file_handle, starting at character 'start', and assigns the string read to x. The file must have been opened as "random" for this operation to be used.

<puts>
puts(xxx,xxx,xxx);

<HELP>
puts(file_handle,start,stg); statements writes the string 'stg' to the file referenced by file_handle, starting at character 'start'. The file, which is enlarged as much as necessary, must have been opened as "random" for this operation to be used.

<printa>
printa(xxx,xxx," ",xxx);  

<HELP>
printa(file_handle,x,y) statements convert their sucessive arguments (other than the first) to strings and print them to the file represented by 'file_handle'. A newline is written after the final character printed. To suppress this action, use 'nprinta' instead.

<nprinta>
nprinta(xxx,xxx," ",xxx);  

<HELP>
nprinta(file_handle,x,y) statement converts their sucessive arguments (other than the first) to strings and print them to the file represented by 'file_handle', without writing a newline after the final character printed.

<reada>
reada(xxx,xxx,xxx);  

<HELP>
read(file_handle,x,y); statements read one complete SETL object from the file represented by 'file_handle' for each of their (variable number of) arguments, and assign it to this argument. It generates an error it it encounters a quantity which is not the legal print form of a SETL object.   

<eof()>
eof() 
<HELP>
The parameterless function eof() returns true if the last input statement executed ecountered an end of file; false otherwise.

<abend_trap>
abend_trap := xxx;

<HELP>
If a value (which must be a parameterless procedure) has been supplied for the special variable 'abend_trap', it will be executed when and if its enveloping SETL program has generated an error, replacing the automatic abort which would otherwise take place. This 'customized abend' routie should simply print some final diagnostic imformation and then stop. It should be written carefully to be error-free, since fatal errors with abend routines may have unpredictable results.

An example of use is 

	program test;		-- illustration of the use of 'abend_trap'
	var step;
	
	abend_trap := lambda(); print("An error accured during step: ",step); stop; end lambda;

	step := 1; x := 0;
	step := 2; x +:= "some string";
		
	end test;
	
<stop>
stop;

<HELP>
The stop; statement terminates SETL execution immediately. 
	
<assert>
assert(xxx);

<HELP>
The assert(expn) statement, most commonly used during debugging,  asserts that its argument expression evaluates to true, and othrwise can stop execution. It operates in one of three way, depending on a preference setting: (i) assertions can be skipped altogether, tested with failed assertons stopping the program, or logged if successful, with failed assertons stopping the program. 
 
<sel>
sel xxx(xxx),xxx(xxx);

<HELP>
A declaration like

	sel x(1),y(2),z(3); 

defines the names which appear in it as synonyms for the tuple components selected by the numbers that the statement associates with them, and then allows C-like 'field' syntax, e.g. 
t.x, t.y, etc. to be used as a synonym for t(1), t(2) etc., in both 'evaluating' and 'assigning' positions. For example,  

	t := []; t.x := 22; print(t.x);

prints 22.

<OM>
OM
<HELP>
OM is the standard SETL 'undefined' quantity.

<numerics>
 1_000_000
<HELP>
Integer numerics can either be written in standard decimal format, e.g. 999999, or to any base n in the format n#xxxx.., as for example the hexadecimal 16#1234567890abcdef, or the binary 2#101101111. Underscores are allowed as punctuation marks in numerics, e.g we can write this same three quantities as 999_999, 16#1_234_567_890_abc_def, and 2#101_101_111. Floating point quantites can be written either standard decimal or in scientific notation, and to any base, as e.g. 1.5, 1.5E10, 1.5E-10, 2#1.01101111E8.  

<special_chars>
 "\n\x00"
<HELP>
 The special characters which have SETL 'escape' representations within quoted strings are " (which is "\""), \ (which is "\\"), \n (newline), \r (carriage return), \t (tab) \0 (zero bytes), and \f (form feed). Any characre can be represented as \xff in terms of its hexadecimal code. The char(n) function maps each integer in the range 0..255 into the character with numeric code n, and abs(c) maps in the other direction, so we have abs(char(n)) = n for all in the range 0..255, and "\xff" = char(16#xy) for all letters x,y in the hexadecimal range 0..f.
<arb>
arb xxx
<HELP>
The arb operator (which is monadic) returns an arbitrary element of the set or tuple x, or OM if this is empty.

<domain>
domain xxx
<HELP>
domain x returns the domain of x, which must be a map. 

<range>
range xxx
<HELP>
range x returns the range of x, which must be a map. 

<from>
xxx from xxx;

<HELP>
x from t; removes the last element from the tuple t, or any element of t if t is a set, and assigns it to x. x becomes OM if t is empty. x can be any expression which can appear to the left of an assignment operator; t can be any expression which can appear to the left or right of  an assignment operator.

<fromb>
xxx fromb xxx;

<HELP>
x fromb t; removes the first element from the tuple t and assigns it to x. x becomes OM if t is empty. x can be any expression which can appear to the left of an assignment operator; t can be any expression which can appear to the left or right of  an assignment operator.

<frome>
xxx frome xxx;

<HELP>
x frome t; removes the last element from the tuple t and assigns it to x. x becomes OM if t is empty. x can be any expression which can appear to the left of an assignment operator; t can be any expression which can appear to the left or right of  an assignment operator.

<not>
not xxx
<HELP>
not x is the negation of the boolean quantity x, i.e. is true if x is false, false if x is true.

<and>
xxx and xxx
<HELP>
x and y is the conjunction of the boolean quantities x and y, i.e. is true if both are true, otherwise false.

<or>
xxx or xxx
<HELP>
x or y is the disjunction of the boolean quantities x and y, i.e. is true if either is true, otherwise false..

<min>
xxx min xxx
<HELP>
x min y is the minimum of the (integer or real) quantities x and y.

<max>
xxx max xxx
<HELP>
x max y is the maximum of the (integer or real) quantities x and y.

<SECTION=Functs>
<cos()>
cos(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<sin()>
sin(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<tan()>
tan(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<acos()>
acos(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<asin()>
asin(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<atan()>
atan(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<atan2>
atan2(xxx,xxx)
<HELP>
The  function atan2(x,y) returns the inverse tangent of the quotient of the two real quantities x and y.

<log(xxx)>
log(xxx)
<HELP>
SETL provides the standard (base e) exponential and logaritmic functions exp and log.

<exp()>
exp(xxx)
<HELP>
SETL provides the standard (base e) exponential and logaritmic functions exp and log.

<sqrt()>
sqrt()
<HELP>
sqrt(x) returns the square root of the real quantity x.

<tanh()>
tanh(xxx)
<HELP>
tanh(x) returns the hypebolic tangent of the real quantity x.

<str()>
str(xxx)
<HELP>
The str(x) function maps any SETL value to its string representation.

<unstr()>
unstr(xxx)
<HELP>
The unstr(x) function reads and the print form of a SETL value and returns the value (except in some ambiguous cases.) The binstr/unbinstr operations can be used instead of str/unstr to avoid these ambiguities.

<binstr()>
binstr(xxx)
<HELP>
The binstr(x) function maps any SETL value to a special binary string representation from which x can be reconstructed unambiguously using 'unbinstr'. That is, unbinstr(binstr(x)) is always x. The only exceptions are for values x involving atoms or procedures; these may not be reconstructible in subseqent runs, when atoms can be renumbered, or after recompilation of procedures written by the binstr operator. See the fuller SETL documentation for a more detailed discussion of this point.

<unbinstr()>
unbinstr(xxx)
<HELP>
The binstr(x) function maps any SETL value to a special binary string representation from which x can be reconstructed unambiguously using 'unbinstr'. That is, unbinstr(binstr(x)) is always x. The only exceptions are for values x involving atoms or procedures; these may not be reconstructible in subseqent runs, when atoms can be renumbered, or after recompilation of procedures written by the binstr operator. See the fuller SETL documentation for a more detailed discussion of this point.

<char()>
char(xxx)
<HELP>
The char(n) function maps each integer in the range 0..255 into the character with numeric code n, and abs(c) maps in the other direction, so we have abs(char(n)) = n for all in the range 0..255.

<newat()>
newat()
<HELP>
The parameterless newat() function generates a new SETL atom each time it is called.

<with>
xxx with xxx
<HELP>
s with x returns a set or tuple, otherwise identical to s, to which x has been added. If s is a tuple, x is added at the end.

<less>
xxx less xxx
<HELP>
s less x returns a set, otherwise identical to s, from which x has been removed.

<lessf>
xxx lessf xxx
<HELP>
f lessf x returns a map, otherwise identical to f, from which all pairs starting with x have been removed.

<mod>
xxx mod xxx
<HELP>
n mod m is the remainder of the integer n modulo m.

<pow>
pow xxx 
<HELP>
pow s returns the set of all subsets of s

<npow>
xxx npow xxx
<HELP>
's npow n' and 'n npow s' both return the set of all subsets of s containing exactly n elements.
 
<time()>
time()
<HELP>
The parameterless functions time() and date() produce stings representing the current time and date, as e.g. 19:20:34, 12/15/98.
 
<date()>
date()
<HELP>
The parameterless functions time() and date() produce stings representing the current time and date, as e.g. 19:20:34, 12/15/98.
 
<float()>
float(xxx)
<HELP>
float(x) converts the integer value x to a real quantity, rounding it to the available precision if necessary.

<abs()>
abs(xxx)
<HELP>
abs(x) returns the absolute value of the integer or real quantity x. If x is a single character, abs(x) returns its hexadecimal code, as an integer between 0 and 255.

<floor()>
floor(xxx)
<HELP>
floor(x) converts the floating point value x to the nearest integer that is no larger.

<ceil()>
ceil(xxx)
<HELP>
ceil(x) converts the floating point value x to the nearest integer that is no smaller.

<fix()>
fix(xxx)
<HELP>
fix(x) converts the floating point value x to the nearest integer.

<sign()>
sign(xxx)
<HELP>
sign(x) returns the sign of the real or integer quantity x, as 1 or -1.

<even()>
even(xxx)
<HELP>
even(x) returns the Boolean value 'true' if the integer x is even, false otherwise.

<odd()>
odd(xxx)
<HELP>
odd(x) returns the Boolean value 'true' if the integer x is odd, false otherwise.

<type()>
type(xxx)
<HELP>
The type(x) function maps each SETL value x into a capitalized string representing its type, e.g. ATOM, REAL, SET, BOOLEAN, STRING, TUPLE, INTEGER, PROCEDURE.

<is_atom()>
is_atom(xxx)
<HELP>
is_atom(x) returns the Boolean value 'true' if x is an atom, false otherwise.

<is_real()>
is_real(xxx)
<HELP>
is_real(x) returns the Boolean value 'true' if x is a real number, false otherwise.

<is_set()>
is_set(xxx)
<HELP>
is_set(x) returns the Boolean value 'true' if x is a set, false otherwise.

<is_map()>
is_map(xxx)
<HELP>
is_map(x) returns the Boolean value 'true' if x is a set all of whose elements are tuples of length 2, false otherwise.

<is_boolean()>
is_boolean(xxx)
<HELP>
is_boolean(x) returns the Boolean value 'true' if x is a boolean quantity, false otherwise.

<is_string()>
is_string(xxx)
<HELP>
is_string(x) returns the Boolean value 'true' if x is a string, false otherwise.

<is_tuple()>
is_tuple(xxx)
<HELP>
is_tuple(x) returns the Boolean value 'true' if x is a tuple, false otherwise.

<is_integer()>
is_integer(xxx)
<HELP>
is_integer(x) returns the Boolean value 'true' if x is an integer, false otherwise.

<is_procedure()>
is_procedure(xxx)
<HELP>
is_procedure(x) returns the Boolean value 'true' if x is a procedure, false otherwise.

<len>
len(xxx,xxx)
<HELP>
The function len(stg,n) removes and returns the first n characters of stg, or the whole of stg if stg is less than n characters long.

<any>
any(xxx,xxx)
<HELP>
The function any(stg,pat_stg) removes and returns the first character of stg if it belongs to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<notany>
notany(xxx,xxx)
<HELP>
The function notany(stg,pat_stg) removes and returns the first character of stg if it does not belong to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<span>
span(xxx,xxx)
<HELP>
The function span(stg,pat_stg) removes and returns the longest initial run of characters of stg all of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<break>
break(xxx,xxx)
<HELP>
The function break(stg,pat_stg) removes and returns the longest initial run of characters of stg none of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<match>
match(xxx,xxx)
<HELP>
The function match(stg,pat_stg) removes an initial segment of stg if it matches pat_stg exactly. Otherwise it returns a null string and leaves stg unmodified. 

<lpad>
lpad(xxx,xxx)
<HELP>
The function lpad(stg,n) pads stg on the left with blanks to make it n characters long. if stg is already longer than n characters it is unmodified. 

<rlen>
rlen(xxx,xxx)
<HELP>
The function rlen(stg,n) removes and returns the last n characters of stg, or the whole of stg if stg is less than n characters long.

<rany>
rlen(xxx,xxx)
<HELP>
The function rany(stg,pat_stg) removes and returns the last character of stg if it belongs to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<rnotany>
rnotany(xxx,xxx)
<HELP>
The function rnotany(stg,pat_stg) removes and returns the last character of stg if it does not belong to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<rspan>
rspan(xxx,xxx)
<HELP>
The function rspan(stg,pat_stg) removes and returns the longest terminal run of characters of stg all of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<rbreak>
rbreak(xxx,xxx)
<HELP>
The function rbreak(stg,pat_stg) removes and returns the longest terminal run of characters of stg none of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<rmatch>
rmatch(xxx,xxx)
<HELP>
The function rmatch(stg,pat_stg) removes a terminal segment of stg if it matches pat_stg exactly. Otherwise it returns a null string and leaves stg unmodified. 

<rpad>
rpad(xxx,xxx)
<HELP>
The function rpad(stg,n) pads stg on the right with blanks to make it n characters long. if stg is already longer than n characters it is unmodified. 

<SECTION=ClassPak>
<package>
package xxx; 		-- 
	procedure xxx(); 		-- 
	procedure xxx(); 		-- 

end xxx;

<HELP>
Package header blocks have the form 

	package pak_name; 		
		procedure name(parameter,parameter,); 		
		procedure other_name(parameter,parameter,); 		
			
	end pak_name;

Only procedure header lines, not their full bodies, are listed.  Package header blocks can contain declarations of their variables and constants, which are thereby made public for sharing between the subprocedures of a program which uses the package and all the subprocedures of the package.

Package body blocks have the form 

	package body name; 		

		procedure name(parameter,parameter,); 		
			more_statements
		end name;
	
		procedure other_name(parameter,parameter,); 		
			other_statements
	end name;

They obey the same syntactic and sematic rules as programs, but contain no 'main program block'.

<packagebody>
package body xxx; 		-- 

	procedure xxx(); 		-- 
	
		return zzz;
	end xxx;

	procedure xxx(); 		-- 
	
		return zzz;
	end xxx;

end xxx;

<HELP>
Package header blocks have the form 

	package pak_name; 		
		procedure name(parameter,parameter,); 		
		procedure other_name(parameter,parameter,); 		
			
	end pak_name;

Only procedure header lines, not their full bodies, are listed.  Package header blocks can contain declarations of their variables and constants, which are thereby made public for sharing between the subprocedures of a program which uses the package and all the subprocedures of the package.

Package body blocks have the form 

	package body name; 		

		procedure name(parameter,parameter,); 		
			more_statements
		end name;
	
		procedure other_name(parameter,parameter,); 		
			other_statements
	end name;

They obey the same syntactic and sematic rules as programs, but contain no 'main program block'.

<nativepackage>
native package xxx; 		-- 
	procedure xxx(); 		-- 
	procedure xxx(); 		-- 

end xxx;

<HELP>
Native package blocks  have the form 

	native package pak_name;
		procedure name(parameter,parameter,); 		
		procedure other_name(parameter,parameter,); 		
			
	end pak_name;

Only procedure header lines, not their full bodies, are listed. The native procedures referenced in such a block must be supplied in a C library included in a plugins folder contained in the same fodler as the SETL interpreter application. This library must have the form detailed in the full SETL reference document.

<class>
class xxx; 		-- 

end xxx;

<HELP>
Class header blocks and their associated class body blocks are used together to define new classes of SETL objects. Class header blocks have the form 

	class class_name; 		
		procedure name(parameter,parameter,..); 		
		procedure other_name(parameter,parameter,..); 		
			
	end class_name;

Only procedure header lines, not their full bodies, are listed.  Class header blocks can contain declarations of their variables and constants, which are thereby made public for sharing between the subprocedures of a program which uses the class and all the subprocedures of the class.
<class body>
class body xxx; 		-- 

end xxx;

<HELP>
Class body blocks and their associated class header blocks are used together to define new classes of SETL objects. Class body blocks have the form 

	class class_name; 		
		procedure name(parameter,parameter,..); 
			statements...
		end name;	

		procedure other_name(parameter,parameter,..); 		
			statements...
		end name;	
			
	end class_name;

The procedure definitions seen must include definitions of all the procedures listed in the associated class header.
 
Class bodies can also contain procedures with headers like 

		procedure self + x;		or 		procedure arb self;
		
which redefine built-in SETL operators for objects of the class. These use the keyword 'self' and are terminated by the single keyword 'end;'.

Class bodies can contain declarations of their variables and constants, which are thereby made privately available to all the procedures of the class and of other classes which inherit from it.
<classvar>
	class var xxx , xxx := xxx;

<HELP>
var (and const) declarations of several kinds can appear in classes and class bodies. Ordinary var declarations can appear at the start of a classes and class body. These declare 'instance variables', of which an individual copy is created for each subsequently created object obj of the class C. Instance variables x declared in the class (i.e. class header) are public, that is acessible (via the syntax obj.x) to all other programs, packages, and classes which use C.  Instance variables declared in the class body are private to C, that is, acessible only inside the procedures of C and of other classes which inherit from C.

var declarations of the modified form 

		class var x,..
		
declare 'class variables', of which only copy, created within the class itself, is shared by all subsequently created objects obj of the class. Class variables x declared in the class (i.e. class header) are public, that is acessible (via the syntax obj.x) to all other programs, packages, and classes which use C.  Class variables declared in the class body are private to C, that is, acessible only inside the procedures of C and of other classes which inherit from C.

The same rules apply to const declarations.
<create>
procedure create(xxx);		--

end create;

<HELP>
SETL objects of a class named class_name are created by calls of the form 

			obj := class_name(params..);

which use the name of their class as a fucntion name and which supply the paametrs (if any) reqired by the class' 'create' routine (if any has been supplied.) Space is allocated for this new object, all its instance variables are  given their desingnated initial values, and the new object is returned, by this statement itself, so no 'create' routine is actually required. However, if such a routine is supplied, it is called just before the newly created object is returned, snd so can be used to perform any additional initializations needed.

Se the discussion of 'inherit' for an explanation of the way in which inherited parts of newly created objects can be initialized.
<self>
self
<HELP>
The keyword 'self' is used within the procedures of a class to designate the 'currently active'. When such a procedure p is invoked using the standard 'method' syntax obj.p(params..), 'self' refers to 'obj'; similarly for procedures with headers like

		procedure self + x;		or 		procedure self(x) := y;

when invoked by operations like obj + xx or obj(xx) := yy.

<self*>
procedure self * xxx;		--

	return zzz;
end;

<HELP>
All standard SETL binary operations, other than 'in' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self * xxx;				procedure xxx * self;
			statements...			or			statements...
		end;								end;

in the class' body. Both forms can be included together.

<*self>
procedure xxx * self;		--

	return zzz;
end;

<HELP>
All standard SETL binary operations, other than 'in' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self * xxx;				procedure xxx * self;
			statements...			or			statements...
		end;								end;

in the class' body. Both forms can be included together.

<self()>
procedure self(xxx);		--

	return zzz;
end;

<HELP>
The 'component retrieval' operation f(x) can be redefined for objects of a given class by including an operation definition of the form 

		procedure self(xxx);
			statements...
		end;

in the class' body.

<self():=>
procedure self(xxx) := yyy;		--

	return zzz;
end;

<HELP>
The 'component assignment' operation f(x) := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure self(xxx) := yyy;
			statements...
		end;

in the class' body.

<self{}>
procedure self{xxx};		--

	return zzz;
end;

<HELP>
The 'set image retrieval' operation f{x} can be redefined for objects of a given class by including an operation definition of the form 

		procedure self{xxx};
			statements...
		end;

in the class' body.

<self{}:=>
procedure self{xxx} := yyy;		--

	return zzz;
end;

<HELP>
The 'set image assignment' operation f{x} := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure self{xxx} := yyy;
			statements...
		end;

in the class' body.

<#self>
procedure #self;		--

	return zzz;
end;

<HELP>
The cardinality operation #x can be redefined for objects of a given class by including an operation definition of the form 

		procedure #self;
			statements...
		end;

in the class' body.

<-self>
procedure -self;		--

	return zzz;
end;

<HELP>
The negation operation -x can be redefined for objects of a given class by including an operation definition of the form 

		procedure -self;
			statements...
		end;

in the class' body.

<powself>
procedure pow self;		--

end;

<HELP>
The power set operation pow x can be redefined for objects of a given class by including an operation definition of the form 

		procedure pow self;
			statements...
		end;

in the class' body.

<notself>
procedure not self;		--

end;

<HELP>
The logical negation operation 'not x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure not self;
			statements...
		end;

in the class' body.

<domainself>
procedure domain self;		--

end;

<HELP>
The domain operation 'domain x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure domain self;
			statements...
		end;

in the class' body.

<rangeself>
procedure range self;		--

end;

<HELP>
The range operation 'range x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self;
			statements...
		end;

in the class' body.

<self(i..)>
procedure self(xxx..);		--

end;

<HELP>
The tail slice retrieval operation t(i..) can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..);
			statements...
		end;

in the class' body.

<self(i..):=>
procedure self(xxx..) := yyy;		--

end;

<HELP>
The tail slice assignment operation t(i..) := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..) := yyy;
			statements...
		end;

in the class' body.

<self(i..j)>
procedure self(xxx..yyy);		--

end;

<HELP>
The slice retrieval operation t(i..j) can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..yyy);
			statements...
		end;

in the class' body.

<self(i..j}:=>
procedure self(xxx..yyy) := zzz;		--

end;

<HELP>
The slice assignment operation t(i..j) := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..yyy) := zzz;
			statements...
		end;

in the class' body.

<fromself>
procedure from self;		--

end;

<HELP>
The extraction operation 'from x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure from self;
			statements...
		end;

in the class' body. The same applies to the operations 'fromb' and frome'.

<inself(iter)>
procedure iterator_start;		--

end iterator_start;

procedure iterator_next;		--

end iterator_next;

<HELP>
SETL iterators of the form .. x in obj .. can be redefined for objects of a given class by including a pair of parameterless procedures

		procedure iterator_start;				procedure iterator_next;
			statements...			and				statements...
		end iterator_start;						end iterator_next;

in the class' body. The iterator_start routine will be called as the iteration is entered, and should initialize whatever internal data objects are needed for the iteration. The iterator_next routine will be called once for each iteration cycle, and should return a singleton tuple whose one component is the next 'supbart' of obj to be returned by the iteration .. x in obj .. To terminate iteration, the value OM should be returned instead of a singleton tuple.

SETL iterators of the form .. x = obj(y) .. are treated as synonyms for iterators

				 .. [x,y] in obj ..

and so can be redefined for objects in the same way.

<=self{}>
procedure set_iterator_start;		--

end set_iterator_start;

procedure set_iterator_next;		--

end set_iterator_next;

<HELP>
SETL iterators of the form .. x = obj{y} .. can be redefined for objects of a given class by including a pair of parameterless procedures

		procedure set_iterator_start;				procedure set_iterator_next;
			statements...				and				statements...
		end set_iterator_start;						end set_iterator_next;

in the class' body. The set_iterator_start routine will be called as the iteration is entered, and should initialize whatever internal data objects are needed for the iteration. The set_iterator_next routine will be called once for each iteration cycle, and should return a singleton tuple whose one component is the pair [x,y] of values to be returned by the iteration .. x = obj{y} .. To terminate iteration, the value OM should be returned instead of a singleton tuple.

<selfstr>
procedure selfstr(xxx);		--

end;

<HELP>
The built-in function 'str(x)', which produces a SETL object's string form, can be redefined for objects of a given class by including a parameterless operation definition of the form 

		procedure selfstr;
			statements...
		end;

in the class' body. Since this function is used by the functions 'print' and 'printa' to convert objects to strings, this defintion will also control the way in which objects of the class print.

<selfand>
procedure self and xxx;		--

end;

<HELP>
The SETL logical binary operations 'and' and 'or' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self and xxx;				procedure xxx and self;
			statements...			or			statements...
		end;								end;

in the class' body. Both forms can be included together.

<selfnpow>
procedure self npow xxx;		--

end;

<HELP>
The SETL binary powerset operation 'npow' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self npow xxx;			procedure xxx npow self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfwith>
procedure self with xxx;		--

end;

<HELP>
The SETL binary operations 'with', 'less', and 'lessf' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self with xxx;			procedure xxx with self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfless>
procedure self less xxx;		--

end;

<HELP>
The SETL binary powerset operations 'with', 'less', and 'lessf' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self less xxx;			procedure xxx less self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selflessf>
procedure self lessf xxx;		--

end;

<HELP>
The SETL binary powerset operations 'with', 'less', and 'lessf' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self less lessf;			procedure xxx lessf self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfmod>
procedure self mod xxx;		--

end;

<HELP>
The SETL operations 'mod'can be redefined for objects of a given class by including an operation definition of the form 

		procedure self mod lessf;			procedure xxx mod self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfmax>
procedure self max xxx;		--

end;

<HELP>
The SETL binary operations 'max' and 'min' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self max lessf;			procedure xxx max self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<inherit>
inherit xxx,xxx;

<HELP>
Any SETL class C can be declared to inherit part of its structure form a list of previously defined classes C',C''... This is done by including one or more declarations of the form

		inherit C',C'',...; 

at the start of C's class definition (i.e. header block). This causes a copy of every instance and class variable of C', C'',... to be incorporated into every object of type C, and (if there are no name conflicts) to be available to such objects under their original names. Similarly every method defined for objects of type C', C'' becomes available to objects of class C under its original names (again provided that there are no name conflicts.)

The definition of any constant, variable or procedure in any of C', C'',... can be over-ridden in C by defining a constant, variable or procedure having the same name. Aside from this, if any two of C', C''.. define conflicting constants, variables or procedures having the same name 'name', then this name becomes unavailable to objects of type C. Howerer, reference to the constants, variables or procedures are still possible by using the name in an explicitly qualified form like C'.name or C''.name.

<SECTION=Widgets>
<template>
program test;	-- standard template for interactive programs
use tkw,string_utility_pak;		-- use the main widget class

var Tk,global_1,global_2,global_3;

	Tk := tkw(); Tk(OM) := "Caption";						-- create the Tk interpreter
	
			-- widgets can be put into a frame, or directly into Tk
	parent := Tk("frame","100,50"); parent("side") := "top"; 
	parent("background") := "#aaaaaa";	-- grey background
	
	parent2 := Tk("frame","100,50"); parent2("side") := "top"; 
	parent2("background") := "#cccccc";	-- lighter grey background
	
			-- *** create all the other interface widgets by inserting code here *** 
			
	Tk.mainloop();		-- enter the Tk main loop

	procedure my_procedure();	-- procedures go here
		
	end my_procedure;

end test;

<HELP>
This is a standard template for starting to develop interactive programs.
<toplevel>

toplev := parent("toplevel","100,100");		-- giving initial height and width
toplev(OM) := "Caption";

<HELP>
Attributes are: height, width, background, cursor, borderwidth, highlightbackground,
highlightcolor, highlightthickness, menu, relief, takefocus, screen, visual 

'toplevel' widgets are self-standing windows of whatever kinds are available. They are created by a command of the form 

	toplevel_name := tkw_name("toplevel","999,999");

where 'tkw_name' is the name of the master widget object. All other widgets are then created and arranged hierarchically within the toplevel' widgets opened.

Each toplevel can have its own menubar.

use				- modifier for create command: embeds window in pre-existing window????

The attributes of a toplevel are as follows:

		height, width			- window height and width 
		background				- window background color 
		cursor					- cursor to display when mouse is over window
		borderwidth				- width of border around window
		highlightbackground		- border color when window does not have focus
		highlightcolor			- border color when window does have focus
		highlightthickness		- window border thickness for hilighting 
		menu					- menu to use for menubar
		relief					- flat, sunken, raised, groove, or ridge
		takefocus				- see explanation found under the help keyword 'focus'
		
		screen					- screen on which toplevel is placed (XWindows only)
		visual					- color mapping to be used within window  (XWindows mainly)
								- see help item for 'visual'

<frame>

fr := parent("frame","100,100"); fr("side") := "top";	-- if packed; or left,right,bottom
fr("background") := "#ffaaaa";		-- for a pink background

<HELP>
Attributes are: height, width, background, cursor, borderwidth, highlightbackground,
highlightthickness, relief, takefocus

frames are rectangular areas within toplevel windows or other frames, within which other widgets can be arranged. They are created by commands of the form 

	xxx := parent_frame("frame");

Other widgets can then be created and arranged hierarchically within such frames.

The attributes of a frame are as follows:

		height, width			- frame height and width 
		background				- frame background color 
		cursor					- cursor to display when mouse is over frame
		borderwidth				- width of border around frame
		highlightbackground		- border color when frame does not have focus
		highlightcolor			- border color when frame does have focus
		highlightthickness		- frame border thickness for hilighting 
		relief					- flat, sunken, raised, groove, or ridge
		takefocus				- see explanation found under the help keyword 'focus'

<canvas>
ca := parent("canvas","300,100"); ca("side") := "left";	-- if packed; or left,right,bottom

<HELP> 
Attributes are: height, width, background, borderwidth, cursor, insertbackground, 
insertborderwidth, insertofftime, insertontime, highlightbackground, highlightcolor,
highlightthickness, relief, coords, class, colormap, container, menu, screen,
takefocus, use, visual, closenough, confine, selectbackground, selectforeground, 
selectborderwidth, xscrollincrement, yscrollincrement,
scrollincrement, scrollregion 

Canvases are rectangular areas in which geometric shapes and other widgets can be draw at specified positions. The objects which can be drawn into a canvas are called 'canvas items'. The geometric objects allowed are  arc, bitmap, image, line, oval, polygon, text, and image. Additionally, any other widget, including canvases and frames, can drawn to a canvas, so that canvases can be structured as collages of basic geometric abjects and subcanvases.

Canvases can occupy rectangles larger than that in which they are displayed, in which case they can be scrolled.

Each type of canvas item has its own set of attributes. The attributes of a canvas itself are as follows:
 
		height, width			- canvas height and width 
		background				- canvas background color 
		borderwidth				- width of border around canvas
		cursor					- cursor to display when mouse is over canvas
		insertbackground		- color of insertion cursor
		insertborderwidth		- border width for insertion cursor, if displayed in relief
		insertofftime,insertontime	- blink times for insertion cursor
		highlightbackground		- border color when canvas does not have focus
		highlightcolor			- border color when canvas does have focus
		highlightthickness		- border thickness for hilighting 
		relief					- 3d relief of canvas border
		coords					- 
		class					- 
		colormap				- 
		container				- 
		menu					- 
		screen					- 
		takefocus				- see explanation found under the help keyword 'focus'
		use						- 
		visual					- 
		closenough				- 
		confine					- 
		selectbackground		- 
		selectforeground		- 
		selectborderwidth		- 
		xscroller				- horizontal scrollbar for the canvas, if any
		yscroller				- vertical scrollbar for the canvas, if any
		yscrollincrement		-
		scrollincrement			-
		scrollregion			-

<canvasitem>
rect := ca("rectangle","20,20,60,40"); rect("fill") := "red";
oval := ca("oval","80,20,120,40"); oval("width") := 5;
line := ca("line","140,20,180,20,180,40,20,40"); line("fill,smooth") := "blue,true";
poly := ca("polygon","140,60,180,60,180,100,20,100"); poly("fill,smooth") := "blue,true";

ct := ca("text","Text in the canvas"); 
ct("coords") := "30,30"; ct("anchor,font") := "nw,{Times 36}";	

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, and text. Additionally, any other widget, including canvases and frames, can drawn to a canvas, so that canvases can be structured as collages of basic geometric objects and subcanvases.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For rectangles, arcs and ovals, these are the left, top, right, bottom of the enclosing rectangle (in the case of arcs, the enclosing rectangle of the oval on which the arc lies.) For lines (open curves) and polygons (closed curves) these are the x and y coordinates of the controlling vertices (note that these curves can be splines.) For bitmaps, images, text, and  these are the x and y coordinates of the item's anchor point (e.g. center.) 

Each item can also have an associated list of tags, given by its "tags" attribute.

Each type of canvas item has its own set of additional attributes. These are listed in the folowing table:
	
	rectangle, oval: 
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior

	arc: 
		style				- pieslice, chord, or arc (circular boundary only)
		start				- starting angle of circular arc, in degrees
		extent				- extent of circular arc, in degrees
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior
		outlinestipple		- pattern for outline
	
	line: (open curve)
		width				- line width
		smooth				- if true, line is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- line color
		stipple				- line pattern
		joinstyle			- line corner join style: bevel, miter, or round
		capstyle			- line end style: butt, projecting, or round		
		arrow				- should arrowheads be drawn: none, first, last, or both
		arrowshape			- tuple [overall length, length from point to line end, width]	
	
	polygon: (closed curve)
		width				- polygon outline width
		smooth				- if true, polygon is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- color for polygon interior
		outline				- color for polygon outline
		stipple				- pattern for arc interior
	
	bitmap: 
		bitmap				- file name or built-in bitmap name defining picture geometry
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		background			- display color for bitmap background
		foreground			- display color for bitmap foreground
	
	image: 
		image				- image object to appear in canvas item
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
	
	text: 
		text				- actual text string
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		font				- text font, e.g. "Times,20,bold"
		justify				- left, right, or center
		fill				- text color
		stipple				- text pattern
		width				- text area width 
	
	widget:
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se

<textwidget>
txt := parent("text","30,10"); txt("side") := "left"; txt(OM) := "Type\ntext\nhere";

<HELP>
text widgets 'tex' are editable single-line text entry areas. The text in a textline widget can be manipulated using string-like syntax: tex(m..n) designates characters m thru n, tex(OM) all the text in the widget, #tex the number of characters of text. In the expression tex(m..n), m and n can either be strings of the form line.char, or one of the following constants, designating special positions in the text within the widget:

	@x,y			- the character at screen point x,y
	end				- last character
	insert			- position of insertion cursor
	tag_name.first	- first character in the range tagged by "tag"
	tag_name.last	- first character after the range tagged by "tag"
	mark_name		- first character after the indicated mark
	current			- the character under the mouse
	some_image		- character position of an embedded image
	some_widget		- character position of an embedded widget

These index expressions can be modified by the addition of the following suffixes:
 
	wordstart		- start of word containing character
	wordend			- start of word containing character
	linestart		- start of line containing character
	lineend			- start of line containing character
	+n				- n characters forward, same line (e.g. "current+15")
	-n				- n characters previous, same line
	+nlines			- n lines forward, same character position (e.g. "current+5lines")
	-nlines			- n lines previous, same line
	
The attributes of text widgets are:

		width, height			- widget horizontal and vertical dimensions
		state					- normal or disabled (if disabled, text is read-only)
		font					- text font
		padx,pady				- extra space around text, inside of border
		foreground				- text color
		background				- text background color
		justify					- left, right, or center
		wrap					- line wrap mode: none, char, or word
		selectbackground		- background color for selected text 
		selectforeground		- foreground color for selected text 
		selectborderwidth		- width of selection border (for 3D selection effect) 
		borderwidth				- extra space around edge of text
		cursor					- cursor to display when mouse is over canvas
		setgrid					- if true, height and width attributes are in character units
		spacing1				- extra space above each unwrapped line
		spacing2				- extra space interior to wrapped lines
		spacing3				- extra space below each unwrapped line
		tabs					- list of tab stops
		insertwidth				- width of insertion cursor
		insertbackground		- color of insertion cursor
		insertborderwidth		- border width for insertion cursor, if displayed in relief
		insertofftime,insertontime	- blink times for insertion cursor
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when widget does not have focus
		highlightcolor			- color of additional border when widget has focus
		relief					- flat, sunken, raised, groove, or ridge
		exportselection			- use XWindows selection export mechanism (XWindows only)
		takefocus				- see explanation found under the help keyword 'focus'
		xscroller				- horizontal scrollbar for the text widget, if any
		yscroller				- vertical scrollbar for the text widget, if any

Special operations available for text widgets are: 
<textitem>
**
<HELP>
text items are items other than character strings that can appear within text widgets. Two types of text item are provided: widget items and image items. When inserted, items of this kind are treated as if they were 'large characters'. Any widget can be inserted into text as a widget item. Besides their inherent attributes, widgets inserted in this way have the following special attributes:

		widget		- the widget to appear
		align		- alignment of widget in surroundig text: top, center, bottom, or baseline
		padx		- extra space at left and right of item
		pady		- extra space at top and bottom of item
		stretch		- if true, widget will stretch to match text layout
 
 Any absolute image can be inserted into text as a text item. Besides their inherent attributes, images inserted in this way have the following special attributes:

		image		- the image to appear
		align		- alignment of widget in surrounding text: top, center, bottom, or baseline
		padx		- extra space at left and right of item
		pady		- extra space at top and bottom of item
		name		- name for this image instance 
<tag>
**

<HELP>
Tags are used to mark ranges of text in text widgets, and sets of graphic items in canvases.

<focus>
for j in [1..5] loop 
	but := Tk("button","Click" + str(j)); but("side") := "left"; 
	but{OM} := setcolor(but); 
	but("takefocus") := lambda(but_name);  
				but := Tk.obj_from_tkname(but_name(1));
				but("foreground") := "blue"; return 1; 
			end lambda; 
end loop;
procedure setcolor(but); return lambda(); but("foreground") := "red"; end lambda; end setcolor;

<HELP>
The 'focus' can be passed among the widgets in a window by hitting the tab key. This moves the focus forward in the circular order of these widgets; hitting Shift-tab moves the focus backward in this circular order. The 'takefocus' attribute of widgets controls the way in which they react to the arrival of the focus. A widget whose 'takefocus' attribute is set to 0 will always pass the focus along in circular order when it arrives; a widget whose 'takefocus' attribute is set to 1 will always take the focus when it arrives, but do nothing else. The 'takefocus' attribute can also be set to a null string, in which case default rules, which in some cases reflect the state of the widgets the circular order of widgets, will decide whether each widget accepts the focus or passes it along. Finally, a SETL procedure FP can be assigned as the value of a widget's 'takefocus' attribute. This procedure will be called as soon as focus arrives at the widget, the Tk 'string name' of SN the widget will be passed to it. (The widget object itself can be recovered from this internal 'string name' by using the function Tk.obj_from_tkname(SN).) The procedure FP should return 0, 1, or a blank string, depending on whether the widget is to refuse the focus and pass it along to the next widget in circular order, or to take the focus, or to use the default rules mentioned above to make this decision. 

When a widget has the 'focus', the principal command (if any) associated with it can be executed by hitting the space bar. 

<textline>
tline := parent("entry",30); tline("side") := "left"; tline(OM) := "Type text here";

<HELP>
textline widgets 'texl' are editable single-line text entry areas. The text in a textline widget can be manipulated using string-like syntax: texl(m..n) designates characters m thru n, texl(OM) all the text in the widget, #texl the number of characters of text. In the expression texl(m..n), m and n can either be integers, or one of the following constants, designating special positions in the text within the widget:

	anchor			-- the index of the anchor point (left, right, or center) of the selection
	end				-- last character
	insert			-- position of insertion cursor
	sel.first		-- first selected character
	sel.last		-- last selected character
	
A negative integer -n can be used to designate the character at horizontal screen position n.

The attributes of textline widgets are:

		state					- normal or disabled (if disabled, text is read-only)
		font					- text font
		show					- character to display in place of contents
		foreground				- text color
		background				- text background color
		justify					- left, right, or center
		selectbackground		- background color for selected text 
		selectforeground		- foreground color for selected text 
		selectborderwidth		- width of selection border (for 3D selection effect) 
		borderwidth				- extra space around edge of text
		cursor					- cursor to display when mouse is over canvas
		insertwidth				- width of insertion cursor
		insertbackground		- color of insertion cursor
		insertborderwidth		- border width for insertion cursor, if displayed in relief
		insertofftime,insertontime	- blink times for insertion cursor
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when widget does not have focus
		highlightcolor			- color of additional border when widget has focus
		relief					- flat, sunken, raised, groove, or ridge
		exportselection			- use XWindows selection export mechanism (XWindows only)
		takefocus				- see explanation found under the help keyword 'focus'
		textvariable			- if non-null, names a Tk variable holding the widget's string

Special operations available for textline widgets are: 

	texl.bbox(n);			-- return bounding box of specified character
	texl.icursor_move(n);		-- move the inset cursor to position n
	texl.select(m,n);		-- select characters m to n, or clear the selection
	texl.is_select();		-- test if there is a selection
	texl.select_anchor(m);		-- set the anchor point for the selection???

	texl.xview(n);			-- scroll to make indicated character visible
	texl.xview_percent(p);	-- scroll to place fraction p of string offscreen to the left
	texl.xview_scroll(n,what);	-- scroll n 'units'
	texl.scan_to(x);		-- scroll to indicated position
	texl.scan_mark(x);		-- place mark indicating scroll position???
	texl.index(index_key);	-- get numerical value of index_key, e.g. anchor, end, insert, etc.

<button>
but := parent("button","Label"); but("side") := "left";
but{OM} := Tk.beeper;	-- or any other parameterless function
checkbut := parent("checkbutton","Label2"); checkbut("side") := "left";
radbut1 := parent("radiobutton","Radio1"); radbut1("side") := "left";
radbut2 := parent("radiobutton","Radio2"); radbut2("side") := "left";
radbut1("variable,value") := "x,r1"; radbut2("variable,value") := "x,r2";
-- the common 'variable' and distinct 'values' puts these radiobuttons into the same 'group'

<HELP>
button widgets are graphical buttons generally used to trigger associated commands. They can be created as ordinary buttons, or as checkbuttons, radiobuttons, or menubuttons

The attributes of button widgets are:

		text					- button caption
		state					- normal or disabled (if disabled, text is greyed out)
		width					- button width, in characters 
		height					- button height, in characters 
		borderwidth				- button border width, in pixels 
		image					- image to display instead of text caption
		font					- text font
		anchor					- caption anchor point: n,ne,e,se,s,sw,w,nw, center
		justify					- caption justif. in its rectangle: left, right, or center
		foreground				- text color
		background				- background color 
		activeforeground		- text color when mouse is pressed over button 
		activebackground		- background color when mouse is pressed over button 
		disabledforeground		- text color when button is disabled
		cursor					- cursor to display when mouse is over button
		default					- if true, button is emphasized
		padx,pady				- size of extra padding space around text
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when widget does not have focus
		highlightcolor			- color of additional border when widget has focus		
		takefocus				- see explanation found under the help keyword 'focus'
		textvariable			- if non-null, names a Tk variable holding the button's string
		underline				- index of text character to underline
		wraplength				- maximum line length before caption text wraps

checkbuttons, radiobuttons, and menubuttons have a few additional attributes: 

		direction				- position of menu relative to button (menubuttons)
		indicatoron				- true if button status indicator is displayed
		menu					- menu to display when button pressed (menubuttons)
		offvalue				- button-associated value when not checked (checkbuttons)
		onvalue					- button-associated value when checked (checkbuttons)
		value					- button-associated value when selected (radiobuttons)
		selectcolor				- caption color when check or radio button selected
		selectimage				- image replacing caption when check or radio button selected
		variable				- variable holding button-associated value

<menu>
	mb := parent("menubutton","Pick Something"); mb("side") := "left";	-- create a menubutton
	descriptor := "b:Item1,b:Item2,s,c:Item3,c:Item4";
	mb(OM) := mb("menu",descriptor);				-- attach a menu
													-- #men gives the number of items in men
<HELP>
SETL menus can contain kinds of three button-like items, and one kind of menu-like item, allowing them to be structured hierarchically. Menus are seen as tuples of menu items, which can be of the types "b" (like a button), "c" (like a checkbutton), "r" (like a radiobutton), and "s" (reference to a cascaded submenu). Two simpler kinds of items, called separators (used to separate menu items into groups so as to ease reading), and tearoffs (used to allow menus to be 'torn off', which makes them self-standing till closed), can also appear. 

Menus are created by operations of the form

		parent("menu",descriptor),
		
where 'descriptor' is a string of comma-separated items of the form  'b:label', 'c:label', 'r:label', 's:label', 's' (a separator), and 't' (a tearoff.) 

Menus have attributes, which in some cases can be over-ridden by separate individual attributes assigned to their menu items.

The attributes of menus are:

		type					- normal, menubar, or tearoff
		foreground				- text color
		background				- background color 
		selectcolor				- color for selector in mcheckbutton and mradiobutton entries
		font					- font for entries
		activeforeground		- text color when mouse is over an entry 
		activebackground		- background color when mouse is over an entry  
		disabledforeground		- text color when entry is disabled
		borderwidth				- menu border width, in pixels 
		activeborderwidth		- menu border width, in pixels 
		cursor					- cursor to display when mouse is over menu
		postcommand				- command to execute just before menu is posted 
		tearoffcommand			- command to when menu is torn off 
		takefocus				- see explanation found under the help keyword 'focus'

<menuitem>
**

<HELP>
SETL menus can contain kinds of three button-like items, and one kind of menu-like item, allowing them to be structured hierarchically. Menus are seen as tuples of menu items, which can be of the types "mbutton" (like a button), "mcheckbutton" (like a checkbutton), "mradiobutton" (like a radiobutton), and "msubmenu" (reference to a cascaded submenu). Two simpler kinds of items, "mseparator" (used to separate menu items into groups so as to ease reading), and "mtearoff" (used to allow menus to be 'torn off', which makes them self-standing till closed), can also appear. Menus have attributes, which in some cases can be over-ridden by separate individual attributes assigned to their menu items.

The attributes of menu items are:

		label					- label of entry
		image					- image to display instead of label
		bitmap					- bitmap to display instead of label
		justify					- label justification: left, right, or center
		foreground				- text color
		background				- background color 
		accelerator				- text for keystroke binding reminder 
		selectcolor				- color for selector in mcheckbutton and mradiobutton entries
		state					- normal, active, or disabled
		font					- font for entries
		underline				- index of text character to underline
		activeforeground		- text color when mouse is over an entry 
		activebackground		- background color when mouse is over an entry  
		disabledforeground		- text color when entry is disabled
		borderwidth				- menu border width, in pixels 
		activeborderwidth		- menu border width, in pixels 
		columnbreak				- start a new menu column with this entry
		command					- command to execute when this entry is selected
		variable				- if non-null, names a Tk variable holding selection state
		value					- value for 'variable' when radiobutton is selected
		onvalue					- value for 'variable' when checkbutton is selected
		offvalue				- value for 'variable' when checkbutton is not selected
		hidemargin				- suppress the margin reserved for button indicators
		cursor					- cursor to display when mouse is over menu
		postcommand				- command to execute just before menu is posted 
		tearoffcommand			- command to when menu is torn off 
		takefocus				- see explanation found under the help keyword 'focus'

<checkbutton>
ckbut1 := parent("checkbutton","Label1"); ckbut1("side") := "left";
ckbut2 := parent("checkbutton","Label2"); ckbut2("side") := "left";

<HELP>
checkbuttons are buttons which have two displayable graphic forms, checked and unchecked. They are normally used to display boolean values. Each such button has a special 'variable' attribute x. The value of this variable, which can be read using the operation Tk.getvar(x) and set using the operation Tk.setvar(x,val), determines whether the button is checked or unchecked. To associate a particular value of the groups 'variable' attribute x with these states, we set the 'onvalue' and offvalue attributes of the button. checkbuttons have the following attributes:

		text				- button caption
		font				- button text font
		width				- button width, in characters
		height				- button height, in lines
		anchor				- position of caption within button: n,s,w,e,ne,se,nw,sw or center
		justify				- justification of button text: left, right, or center
		padx				- extra vertical space around caption
		pady				- extra horizontal space around caption
		wraplength			- width of caption text wrap area, in pixels
		underline			- index of caption character to underline (to indicate accelerator)
		textvariable		- surrogate variable for caption text of button 
		state				- normal, disabled, active (pressed)
		indicatoron			- true if button status indicator is displayed
		activeforeground	- color of button text when active
		disabledforeground	- color of button text when disabled
		background			- background color of button text
		bitmap				- bitmap used as button caption alternative
		image				- image used as button caption alternative
		cursor				- cursor to use when mouse is over button
		activebackground	- background color when mouse is over button
		borderwidth			- width of button border
		variable			- surrogate variable for button checked state
		offvalue			- value of variable when button checked
		onvalue				- value of variable when button not checked
		highlightthickness	- thickness of highlight boundary surrounding button
		highlightbackground	- color of highlight surounding button when does not have focus
		highlightcolor		- color of highlight surounding button when has focus
		relief				- button relief: flat, sunken, raise, ridge, or groove
		selectcolor			- color for radio or check button selector
		selectimage			- alternate image for radio or check button selector
		takefocus			- see explanation found under the help keyword 'focus'

<radiobutton>
radbut1 := parent("radiobutton","Radio1"); radbut1("side") := "left";
radbut2 := parent("radiobutton","Radio2"); radbut2("side") := "left";
radbut1("variable,value") := "x,r1"; radbut2("variable,value") := "x,r2";
-- the common 'variable' and distinct 'values' puts these radiobuttons into the same 'group'

<HELP>
radiobuttons are buttons which have two displayable graphic forms, selected and unselected. Buttons of this kind are ordinarily used in groups, of which only one button at a time is on. They display the value of a set of mutually exclusive selections. Such groups are defined by the fact that all the buttons in the group share a common 'variable' attribute x. The value of this variable, which can be read using the operation Tk.getvar(x) and set using the operation Tk.setvar(x,val), determines which of the members of the button group is on. To associate a particular value of the groups 'variable' attribute x with a particular button, we set the 'value' attribute of the button. Radiobuttons have the following attributes:

		text				- button caption
		font				- button text font
		width				- button width, in characters
		height				- button height, in lines
		anchor				- position of caption within button: n,s,w,e,ne,se,nw,sw or center
		justify				- justification of button text: left, right, or center
		padx				- extra vertical space around caption
		pady				- extra horizontal space around caption
		wraplength			- width of caption text wrap area, in pixels
		textvariable		- surrogate variable for caption text of button 
		state				- normal, disabled, active (pressed)
		indicatoron			- true if button status indicator is displayed
		disabledforeground	- color of button text when disabled
		background			- background color of button text
		bitmap				- bitmap used as button caption alternative
		image				- image used as button caption alternative
		cursor				- cursor to use when mouse is over button
		activebackground	- background color when mouse is over button
		borderwidth			- width of button border
		variable			- surrogate variable for button checked state
		value				- value of surrogate variable when radio button selected
		highlightthickness	- thickness of highlight boundary surrounding button
		highlightbackground	- color of highlight surounding button when does not have focus
		highlightcolor		- color of highlight surounding button when has focus
		relief				- button relief: flat, sunken, raise, ridge, or groove
		selectcolor			- color for radio or check button selector
		selectimage			- alternate image for radio or check button selector
		takefocus			- see explanation found under the help keyword 'focus'

<menubutton>
mb := fr("menubutton","Pick Something");  mb("side") := "left";	-- create a menubutton
descriptor := "b:Item1,b:Item2,s,c:Item3,c:Item4";
mb(OM) := mb("menu",descriptor);							-- attach a menu

<HELP>
menubuttons are buttons which display associated menus when pressed. They have a 'menu' attribute whose value is the menu object to display when the button is pressed; and a 'direction' attribute which determines the position of this menu relative to the button. In more detail, menubuttons have the following attributes:

		text				- button caption
		menu				- menu to display when button pressed
		direction			- direction of menu display relative to button: 
								- above, below, left, right, or flush
		font				- button text font
		width				- button width, in characters
		height				- button height, in lines
		anchor				- position of caption within button: n,s,w,e,ne,se,nw,sw or center
		justify				- justification of button text: left, right, or center
		padx				- extra vertical space around caption
		pady				- extra horizontal space around caption
		wraplength			- width of caption text wrap area, in pixels
		underline			- index of caption character to underline (to indicate accelerator)
		textvariable		- surrogate variable for caption text of button 
		state				- normal, disabled, active (pressed)
		activeforeground	- color of button text when active
		disabledforeground	- color of button text when disabled
		background			- background color of button text
		bitmap				- bitmap used as button caption alternative
		image				- image used as button caption alternative
		cursor				- cursor to use when mouse is over button
		activebackground	- background color when mouse is over button
		borderwidth			- width of button border
		highlightthickness	- thickness of highlight boundary surrounding button
		highlightbackground	- color of highlight surounding button when does not have focus
		highlightcolor		- color of highlight surounding button when has focus
		relief				- button relief: flat, sunken, raise, ridge, or groove
		takefocus			- see explanation found under the help keyword 'focus'

<message>
msg := parent("message","Messages\ncan\noccupy\nmany lines"); msg("side") := "left";

<HELP>
Message widgets are used to display multiple lines of non-editable text. Their height is calulated automatically. Their attributes are:

		text					- text of message
		font					- message text font
		anchor					- message text anchor point: n,ne,e,se,s,sw,w,nw, center
		aspect 					- message width, as percentage of height
		justify					- message justif. in its rectangle: left, right, or center
		textvariable			- if non-null, names a Tk variable holding the message's string
								- Note: this over-rides the 'text' attribute if it has been set 
		foreground				- text color
		background				- background color 
		width					- message width, in characters for text 
		borderwidth				- message border width, in pixels 
		relief					- flat, sunken, raised, groove, or ridge
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when label does not have focus
		highlightcolor			- color of additional border when label has focus		
		cursor					- cursor to display when mouse is over message
		takefocus				- see explanation found under the help keyword 'focus'

<label>
lab := parent("label","Labels\ncan\noccupy\nmany lines"); lab("side") := "left";
lab("height") := 3;		-- their height is specified explicitly

<HELP>
Label widgets are used to display multiple lines of non-editable text, images, or bitmaps. Their height in lines is specified explicitly. Their attributes are:

		text					- text of label
		font					- label text font
		bitmap					- bitmap to display instead of label text 
		image					- image to display instead of label text 
		anchor					- label text anchor point: n,ne,e,se,s,sw,w,nw, center
		justify					- label justif. in its rectangle: left, right, or center
		textvariable			- if non-null, names a Tk variable holding the label's string
								- Note: this over-rides the 'text' attribute if it has been set 
		foreground				- text color
		background				- background color 
		width					- label width, in characters for text, pixels for image 
		height					- label height, in characters for text, pixels for image
		borderwidth				- label border width, in pixels 
		relief					- flat, sunken, raised, groove, or ridge
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when label does not have focus
		highlightcolor			- color of additional border when label has focus		
		cursor					- cursor to display when mouse is over label
		padx,pady				- size of extra padding space around label
		takefocus				- see explanation found under the help keyword 'focus'
		wraplength				- width, in pixels, at which wrap begins

<slider>
slider := parent("scale","0,100");  -- parameters are lower and upper limit of slider range
slider("side") := "top"; 
slider("orient") := "horizontal"; 			-- can be 'vertical'
slider("length,width") := "350,10";			-- physical size of slider

<HELP>
Sliders are used to convert positions along a line into numerical values. They consist of a slider bar ('trough') and a sliding element. One can either drag the sliding element, of hold the mouse down in the trough, which causes the sliding element to move toward the mouse position. 

The attributes of sliders are:

		from,to					- minimum and maximum slider values 
		showvalue				- display value with sliding element
		digits					- number of digits in display value, if any
		resolution				- round value to a multiple of this element 
		orient					- horizontal or vertical
		length,width			- long and short dimensions of the slider trough
		sliderlength			- length of the sliding element
		troughcolor				- color of slider bar
		background				- sliding element and surround color 
		activebackground		- color of sliding element when being dragged 
		foreground				- color of caption text
		state					- normal, active, or disabled
		repeatdelay				- delay till auto-stepping if click in trough
		repeatinterval			- delay between auto-steps if click in trough
		bigincrement			- slider step in response to command-left, command-up, etc.
		variable				- if non-null, names a Tk variable holding the slider value
		cursor					- cursor to display when mouse is over slider
		takefocus				- see explanation found under the help keyword 'focus'
		borderwidth				- slider additional border width, in pixels 
		relief					- flat, sunken, raised, groove, or ridge relief for slider bar
		sliderrelief			- flat, sunken, raised, groove, or ridge relief, sliding element
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when slider does not have focus
		highlightcolor			- color of additional border when slider has focus		
		label					- label to be displayed with slider bar
		font					- label font
		tickinterval			- if nonzero, interval at which to display ticks
		command					- command to invoke when value changes????

<map slider>
	use map_slider;		-- use the map_slider class

	map_slidr := map_slider(Tk,"A@0@255@255;B@0@255@0;C@0@255@0;;X@0@255@255;Y@0@255@0;Z@0@255@0",
			lambda(); end lambda);

<HELP>
A map slider is in effect a slider-controlled, numerically valued map whode domain is the set of labels associated with the slider. They are created by calls of the form 

	ms := map_slider(parent_window_or_frame,"descriptor",response_routine);

The descriptor must be a semicolon-delimited string consisting of @-delimed quadruples of the form 

	Label@lower_limit@upper_limit@default value

each defining one slider label, along with the upper and lower limits for the numerical quantity associated with it, and it inital value. The 'response_routine' which will be called whenver a slider-controlled value changes, should be parameterless. To switch the slider to control the value associated with a particular label, simply click on the  label in the visible form of the map_slider. The value currently associated with any label can be retrieved by writing ms("label"), and set by writing ms("label") := val; this last operation alos adjsuts the visible slider position.

<radio_buttons>
	use radio_buttons;		-- use the radio_buttons class

	j := radio_buttons(fr,"rads1,Opaque*,Darkest     ,Lightest     ",lambda(); end lambda);
	j := radio_buttons(fr,"rads2,Copy     *,Drag     ",lambda(); end lambda);

<HELP>
This class gives an easy way of creating groups of radio buttons. These are created by calls of the form

	junk := radio_buttons(parent,descriptor,response);

 A descriptor for the radio buttons class should have the form v,lab1,lab2,...;v',lab1',lab2',...  where each v names the common variable which ties together a group of radio buttons,  and the following labs are the labels for the buttons. The labs can have preceding and trailing blanks which are just used as spacers but are stripped off in the code. The  very last character of one of the labels can be a '*", n which case the corresponding button will be pre-selected when the buttons first appear. 'response' is the parameterless  response routine to be called when one of the buttons is clicked. The label of the currently  selected button in a group is simply Tk.getvar("v"), where v is the designated   variable for the group.  

<simple_menu>
	use simple_menu_pak;		-- use the simple_menu package

	sm := simple_menu(Tk,"Item1,Item2,,Item3,Item4",lambda(choice); end lambda);

<HELP>
This class gives an easy way of creating simple menu buttons.These are created by calls of the form

	junk := simple_menu(parent,descriptor,response);

A descriptor for a menu of this class should have the form lab1,lab2,..., where the labels should be distinct. The labels can have preceding and trailing blanks which are just used as spacers but are stripped off in the code. Empty labels can be used and will generate separators. 'response' is a 1-parameter response routine to which the selected menu item will be passed when a selection is made.

<listbox>
lb := parent("listbox",3); lb("side") := "left";	-- listbox shows 3 elements
lb(1..0) := "Item1,Item2,Item3,Item4,Item5,Item6,Item7,Item8,Item9,Last Item";
				-- listbox contains 10 elements, so a scrollbar is attached
lb("yscroller") := scroller := parent("scrollbar","v,10"); -- attach a scrollbar
lb("width") := 8;

scroller("side,fill") := "left,y"; -- scrollbar fills available vertical space

<HELP>
Listboxes are used to display lists of items for easy choice. SETL sees them as tuples of strings, nmely the strings which appear in the listbox.

The attributes of listboxes are:
		height					- number of listbox lines visible
		width					- width of listbox, in characters
		font					- item text font
		foreground				- color of item text
		background				- item background color 
		selectforeground		- text color of selected items 
		selectbackground		- background color of selected items  
		borderwidth				- extra border width, in pixels, around the listbox
		selectborderwidth		- extra border width around listbox text items for 3D effect
		selectmode				- single, browse, multiple, or extended. See main documentation 
		setgrid					- if true, restict resizing to whole number of lines and chars
		cursor					- cursor to display when mouse is over listbox
		relief					- relief for entire listbox 
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when listbox does not have focus
		highlightcolor			- color of additional border when listbox has focus		
		takefocus				- see explanation found under the help keyword 'focus'
		yscroller				- vertical scrollbar for the listbox, if any
		exportselection			- if true, exports selected text (XWindows only)

<rastport>
	rast.get_img(gr_img,u,v);	-- move a copy of gr_img to position u, v in rastport, and fill it 
								-- with the bitmap data that it overlays in that position 
	rast.put_img(gr_img,x,y);	-- stuff gr_img into rastport at position x, y
<HELP>
	Rastports are a new form of canvas widget, spcific to SETL's interactive environment, for the efficient display of images of 'grlib' type; see the documentation of 'grlib' in the 'libs' section of this help window and in the main SETL documentation. About 2 dozen rastport operations are provided. The two most charatcteristic rastport operations are

		rast.get_img(gr_img,u,v)
	
which moves a copy of gr_img to position u, v in rastport, and fills it with the bitmap data that it overlays in that position; and  

		rast.put_img(gr_img,u,v);

which moves a copy of gr_img to position u, v in rastport, and stuffs the covered pixels of rastport with the contents of gr_img. This is done in-place, and efficiently. 

Variants of these basic operations which combine gr_img with the contents of rastport are also provided. 

	The operations analogous to rast.put_img are:

rast.put_add(gr_img,x,y);
	(inserts the sum of the rastport data and gr_img into rastport)
rast.put_dif(gr_img,x,y);	
	(inserts difference of the rastport data and gr_img into rastport)
rast.put_mul(gr_img,x,y);	
	(inserts product the rastport data and gr_img into rastport)
rast.put_div(gr_img,x,y);	
	(inserts quotient of the rastport data and gr_img into rastport)
rast.put_min(gr_img,x,y);	
	(inserts the min of the rastport data and gr_img into rastport)
rast.put_max(gr_img,x,y);	
	(inserts the max of the rastport data and gr_img into rastport)
rast.put_blend(gr_img,x,y,c1,c2);
	(blends gr_img with underlying rastport data using coefficients c1 and c2, and stuffs the result into rastport)

	The operations analogous to rast.get_img are:

rast.get_add(gr_img,x,y);
	(returns gr_img copy holding sum of rastport data and gr_img)
rast.get_dif(gr_img,x,y);
	(returns gr_img copy holding difference of rastport data and gr_img)
rast.get_mul(gr_img,x,y);
	(returns gr_img copy holding product of rastport data and gr_img)
rast.get_div(gr_img,x,y);
	(returns gr_img copy holding quotient of rastport data and gr_img)
rast.get_min(gr_img,x,y);
	(returns gr_img copy holding min of rastport data and gr_img)
rast.get_max(gr_img,x,y);
	(returns gr_img copy holding max of rastport data and gr_img)
rast.get_blend(gr_img,x,y,c1,c2);
	(blends gr_img with underlying rastport data using coefficients c1 and c2, and returns the result in a copy of gr_img)

	Finally, a set of rotated cases of the put operations are provided. These act like put_img, put_add, but rotate gr_img by 90 degrees before comining it with the rastport data and stuffin the result into the rastport. These operations have forms like rast.put_imgr(gr_img,u,v), and are named put_imgr, put_addr, put_difr, put_mulr, put_divr, put_minr, put_maxr, and put_blendr. put_blendr, like put_blend, has the form

			rast.put_blendr(gr_img,x,y,c1,c2).
		
<scrollbar>
tex := parent("text","60,4"); tex("side") := "left";    -- create a text area
tex("wrap") := "word";
        
sbv := parent("scrollbar","v,10");          -- create a vertical scrollbar
sbv("side,fill") := "left,y";
tex("yscroller") := sbv;
   
<HELP>
Scrollbars are modified sliders, specially adapted to work with canvases, textlines, and text areas, which are the three kinds of widgets that can scroll. It has a draggable sliding element, clickable arrows, and responds with larger jumps to clicks in the scrollbar (i.e. 'trough'.)

The attributes of scrollbars are:
		orient					- horizontal or vertical
		width,height			- long and short dimensions of the scrollbars
		repeatdelay				- delay till auto-stepping if click in trough or arrows
		repeatinterval			- delay between auto-steps if click in trough or arrows
		jump					- if true, scrolling is not dynamic, but applied when drag ends
		troughcolor				- color of scrollbars
		background				- sliding element and surround color 
		activebackground		- color of sliding element when being dragged 
		activerelief			- relief of sliding element when being dragged 
		borderwidth				- scrollbars additional border width, in pixels 
		elementborderwidth		- additional border width for arrows and slider, in pixels 
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when slider does not have focus
		highlightcolor			- color of additional border when slider has focus		
		cursor					- cursor to display when mouse is over scrollbars

<dialog>
Tk("ask_ok","type,default,message") := "ok,ok,Proceed"; 
Tk("ask_ok","type,default,message") := "yesnocancel,no,Do you want to see the rest of these dialogs?";
if dialog_response = "yes" then 
	Tk("ask_file","") := "";  
	Tk("ask_save_file","") := "";  
	Tk("ask_color","initialcolor,title") := "red,Pick a Color";
end if;

<HELP>
The SETL graphical interface provides several types of utility dialogs: "ask", "ask_ok", "ask_file", "ask_save_file", and "ask_color".

The "ask" dialog presents a set of captioned buttons, of which one can be designated as the default, and can include a bitmapped icon.  Its attributes are:
		labels					- list of labels to appear
		default					- number of default label			
		message					- message to appear
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog is to appear
		icon					- bitmap to appear, if any

The "ask_ok" dialog is a specialized variant of the "ask" dialogs, which presents one, two, or three buttons, depending on its type, which can be yesno, ok, okcancel, retrycancel, yesnocancel, or abortretrycancel.  Its attributes are:
		type					- dialog type, as just listed
		default					- number of default label			
		message					- message to appear
		icon					- bitmap to appear, if any
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog is to appear
		
The "ask_file" dialog opens the standard system 'select/open file' utility. Its attributes are:
		filetypes				- list of file types to be shown. If empty, all are shown
								- see the main documentation for the format of this list
		initialdir				- initial directory whose contents shown; current dir if empty
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

The "ask_save_file" dialog opens the standard system 'save file' utility. Its attributes are:
		filetypes				- list of file types to be shown. If empty, all are shown
								- see the main documentation for the format of this list
		initialdir				- initial directory whose contents shown; durrent dir if empty
		initialfile				- default file name
		defaultextension		- default file extension, if none given
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

The "ask_color" dialog opens a color picker. Its attributes are:
		initialcolor			- inital color, when picker dialog opened
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

<filedialog>
	Tk("ask_file","") := "";  		-- dialog for reading a file
	if dialog_response /= "" then the_file := dialog_response; end if;

	Tk("ask_save_file","initialfile") := "useless_junk.jnk";  		-- for saving a file
	if dialog_response /= "" then the_file := dialog_response; end if;

<HELP>
********helptext********
<colorpicker>
Tk("ask_color","initialcolor,title") := "red,Pick a Color";
if dialog_response /= "" then the_color := dialog_response; end if;
<HELP>
The SETL graphical interface provide several types of utility dialogs, including "ask_color", which opens a color picker whose attributes are:
		initialcolor			- inital color, when picker dialog opened
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

<clipboard>
Tk("clipboard") := 3 * Tk("clipboard");		-- copy something, run this program, and then paste it

<HELP>
The 'clipboard' is an in-RAM file of string data used to communicate between separate applications. When a selection is 'copied'  (or 'cut') is most text-oriented applications, a copy of it is put into the keyboard. When the 'paste' operation available in most such applications is used, the text which appears is that contained in the clipboard. The SETL interface provides operations which allow the clipboard contents to be manipulated directly.
These are

	Tk("clipboard")				-- returns the current string value in the clipboard
	Tk("clipboard") := stg;		-- sets the current string value in the clipboard

When communicating via clipboard with another SETL application, it may be convenient to pass a binary string encoding a SETL value (e.g. a map), and to decode it on receipt; although the code for this is simply 
	
	Tk("clipboard") := binstr(x);	and	y := unbinstr(Tk("clipboard"));
	
it allows arbitary SETL values to be passed via the clipboard.

<pack>
msg := parent("message","Long message");  msg("side") := "top";
but := parent("button","Label"); but("side,fill") := "top,y";

msg2 := parent2("message","Long message");  msg2("side") := "top";
but2 := parent2("button","Label"); but2("side,fill") := "top,both";

<HELP>
The items 'packed' into a frame appear in the frame's ordered 'packing list', and their positions and sizes are then calculated using their side, padx, pady, ipadx,ipady, expand, fill, and anchor settings. The packing list is manipulated by setting the 'in' attribute, making assignments to the 'after', 'before', or 'children' attributes, or setting obj("side") := OM to remove it from the packing list to which it belongs. To get or set one of a widget's packing-related attributes (see the list below) an attribute list starting with one of the keywords 'pack or 'side' must be used. Wnen 'pack' is used it plays only a syntactic role, and no attribute value should be assigned to it.    

The attributes involved in widget packing are:
		side				- edge (top, bottom, left, right) toward which widget is packed
		in					- widget, other than parent, in which this widget should be packed
							- Note: can only pack into frame belonging to same toplevel
		after				- widget that this should follow in packing order
		before				- widget that this should precede in packing order
		anchor				- position in available space that item should occupy:
							- (n, s, e, w, ne, se, nw, sw, or center) 
		expand				- if true, widget will claim available space in all directions
		fill				- none, x, y, or both: widget fills empty space in that direction
		padx,pady			- size of extra padding space around item packed
		ipadx,ipady			- size of extra internal padding space around item packed
		children			- ordered list of items packed within a frame
		adjust				- if true, frame will adjust to minimum size required for children

<grid>
msg := parent("message","Long message");  msg("row,column") := "1,1";
but := parent("button","Label"); but("row,column") := "1,2";

msg2 := parent2("message","Long message");  msg2("row,column") := "2,2";
but2 := parent2("button","Label"); but2("row,column,sticky") := "2,1,news";

<HELP>
All the items 'grid-placed' into a frame are assigned roa and column positions within a rectangular arangement of implicit 'boxes', which are given box-sizes just large enough to hole their assigned contents. To get or set one of a widget's grid-placement related attributes (see the list below) an attribute list starting with one of the keywords 'grid', 'row', or 'column' must be used. When 'grid' is used it plays only a syntactic role, and no attribute value should be assigned to it.

The attributes involved in grid placement of widgets are:
		row, column			- row and column in which widget is placed
		rowspan				- number of rows occupied by widget
		columnspan			- number of columns occupied by widget
		in					- widget, other than parent, in which this widget should be placed
							- Note: can only placed in frame belonging to same toplevel
		sticky				- edges in available space to which item should adhere,
							- by enlarging if necessary (n, e, s, and w, e.g 'news') 
		padx,pady			- size of extra padding space around item packed
		ipadx,ipady			- size of extra internal padding space around item packed
		children			- ordered list of items grid-placed within a frame
		adjust				- if true, frame will adjust to minimum size required for children

<place>
but := parent("button","Label"); but("place,x,y") := "5,5";
but2 := parent("button","Label"); but2("place,x,y") := "15,15";

<HELP>
Items are 'manually placed' into a given frame by being assigned a position, height, and width. To get or set one of a widget's manual-placement related attributes (see the list below) an attribute list starting with the keywords 'place'must be used. This plays only a syntactic role, and no attribute value should be assigned to it.

The attributes involved in manual placement of widgets are:
		x,y					- x and y pixel positions of anchor point
		relx,rely			- x and y positions of anchor point, as fraction of frame
		width,height		- pixel width and height of widget
		relwidth,relheight	- width and height of widget, as fraction of frame
		anchor				- point in widget occupying stated position:
							- (n, s, e, w, ne, se, nw, sw, or center) 
		in					- widget, other than parent, in which this widget should be placed
							- Note: can only placed in frame belonging to same toplevel
		children			- ordered list of items manually placed within a frame

<event>
**

<HELP>
For more explanation of the way in which widgets and canvas or text items are made sensitive to events, see the main documentation, or the on-line help item 'binding events'. This section expains the kinds of events available, and the way in which they can be created and transmitted under program control.

Widgets and tags can be sensitive to the variety of events seen in the following list: 

	 buttonpress          - mouse button pressed
	 buttonrelease        - mouse button released
	 keypress             - keyboard key pressed
	 keyrelease           - keyboard key released
	 motion               - mouse moved
	 enter                - mouse enters widget
	 leave                - mouse leaves widget
	 double               - mouse doubleclick
	 triple               - mouse triple
	 focusin              - widget gains keyboard focus
	 focusout             - widget loses keyboard focus
	 map                  - window is opened
	 unmap                - window is iconified
	 circulate            - window stacking order changes
	 visibility           - window visibility has changed
	 destroy              - window was destroyed
	 expose               - window has been exposed
	 configure            - size, position, border, or stacking order has changed
	 gravity              - widget has moved because of change in size of its parent window
	 colormap             - color map has changed
	 activate             - the SETL application has been activated
	 deactivate           - the SETL application has been deactivated
	 reparent             - window has been reparented???
	 property             - a window property has been changed or removed???
	 cut                  - system dependent keypress event designating 'Cut'
	 copy                 - system dependent keypress event designating 'Copy'
	 paste                - system dependent keypress event designating 'Paste'
	 
Each of these events can generates a callback to SETL when it occurs.

One particular type of event is designated as each type of widget's 'principal' event. The following table shows these principal events:

	button		- (first) button down
	menu		- (first) button up
	frame		- mouse motion with (first) button down
	toplevel	- mouse motion with (first) button down
	textline	- loss of focus
	listbox		- (first) button up
	text		- loss of focus
	canvas		- mouse motion with (first) button down
	arc			- (first) button down
	bitmap		- (first) button down
	image		- (first) button down
	line		- (first) button down
	oval		- (first) button down
	polygon		- (first) button down
	rectangle	- (first) button down

Tags in canvases or text (see below) can also be event sensitive; their 'principal' event is (first) button down.

Events normally occur as a result of user mouse or keyboard actions. However, events can be created and transmitted to designated widgets and canvas  under program control. To create and  transmit an event, to a widget W, we write 
	
		W{"event_descriptor:event_fields_signature"} := event_parameter_vals;

where 'event_descriptor' and 'event_fields_signature' have the form detailed in the on-line help item 'binding events' and where 'event_parameter_vals' is either a comma-separated sting or a tuple of corresponding event parameter values. An example is 

	top_frame{"B1-Move:xy"} := "25,25";
	top_frame{"B1-Move"} := "";

As seen, the colon used in this event-binding syntax is only required if a non-empty event_fields_signature follows it.

<timed events>
but := parent("button","Click me"); but("side") := "top";
but("font") := "{Times 12}"; global_1 := but; global_2 := true;
but{OM} := start_it;

procedure start_it(); 		-- start the wild action
	global_1("text") := "Click me again before I go crazy"; 
	global_1{OM} := lambda(); global_2 := global_1; global_1 := OM; end lambda; 
	flicker();		-- start the wild action
end start_it;

procedure flicker();  		-- take the wild action
	if global_1 = OM then 		-- stop when global_1 is dropped
		global_2("text") := "What a relief!"; return; 
	end if;
	global_2 := not global_2; 
	global_1("font") := if not global_2 then "{Times 12}" else "{Times 24}" end if;
	Tk.createtimer(500,flicker);	-- repaet twice each second
end flicker;

<HELP>
SETL callback procedures can be invoked after a specified delay, or whenever the interface quiesces and becomes idle. To set up a timed call, one writes 

			id := Tk.createtimer(interval,SETL_fun);

Here 'interval' is the time, in milliseconds, before the parameterless SETL function 'SETL_fun' is to be invoked. This call returns an identifier for the pending timer event, which can be cancelled any time before it has taken place by writing  

			Tk.cancel(id);

To set up a 'when-idle' call that will be triggered when the interface quiesces, write 

			id := Tk.createtimer(OM,SETL_fun);

<binding events>
but := parent("button","Press and hold me; then release the button");
but("side") := "top";
but{OM} := Tk.beeper;		-- set up button to beep once when released
							-- and 3 times when first pressed
but{"ButtonPress-1"} := lambda(); for j in [1..3] loop Tk.beeper(); end loop; end lambda;
print(but{OM}, " ",but{"ButtonPress-1"});		-- print the assigned procedure names

<HELP>
Event handlers for the various kinds of mouse, keyboard, and other events to which Tk widgets and canvas
items are sensitive are set up by writing nominal assignments having one of the two the syntactic forms 

   widget{"event_descriptor:event_fields_signature"} := SETL_procedure;

  text_widget{"tag_name","event_descriptor:event_fields_signature"} := SETL_procedure;

  canvas{"tag_name","event_descriptor:event_fields_signature"} := SETL_procedure;

The first form is used to assign callback procedures to widget-related events; the second and third to
assign callback procedures to tags in text fields and canvases.

The event_fields_signature should be a string consiting of the  single-character codes for the event parameters to be transmitted to an event's handler (see the on-line help sction 'event parameters'.) When an event of the designated type subsequently occurs, the corresponding parameter values will be read from the 'event record' always associated with the event, and collected into a parameter list. This will be transmitted to the callback procedure, which must have exactly one parameter. 

Examples are 

   top_frame{"B1-Move:xy"} := my_drag_procedure1;
   my_button{"ButtonPress-1"} := my_clickstart_procedure1;
   my_canvas{"all_ovals","ButtonRelease-1:t"} := print_click_time;

As seen, the colon used in this event-binding syntax is only required if a non-empty event_fields_signature follows it.

<event parameters>
but := parent("button","Click me to get the time in milliseconds and the click location"); 
but("side") := "top";
but{"ButtonRelease-1:txy"} := lambda(params); 
									[the_time,x,y] := params; 
									print("time: ",the_time," x: ",x," y: ",y); 
							 end lambda;
		
<HELP>
Events have various possible attributes, which can be transmitted as parameters to their associated callback procedures. As seen in the following table, every possible event attribute has an associated single-character code. 

    CODE    DESCRIPTION OF PARAMETER      EVENTS USED FOR; VALUES

     #    -  event serial number             all events
     a    -  'above' field for event         configure event
     b    -  button number            buttonpress, buttonrelease
     c    -  event count field               expose, map
     d    -  event detail field       enter, leave, focusin, focusout
     f    -  focus value established by event      enter, leave
     h    -  height field                    configure, expose
     k    -  keycode                         keypress, keyrelease
     m    -  mode                     enter, leave, focusin, focusout
     o    -  override redirect               map, reparent, configure
     p    -  place                placeontop, placeonbottom, circulate
     s    -  state                buttonpress, buttonrelease, enter, 
                                  leave, keypress, keyrelease, motion
     t    -  time                            all events
     v    -  value mask                      configure event
     w    -  width                           configure, expose
     x    -  horizontal position, widget relative  all mouse events
     y    -  vertical position, widget relative    all mouse events
     A    -  printing character              keypress, keyrelease
     B    -  border width                    configure event
     E    -  sendevent field                 all events
     K    -  key symbol                      keypress, keyrelease
     N    -  key symbol in decimal           keypress, keyrelease
     R    -  root window id                  all events
     S    -  subwindow id                    all events
     T    -  type field                      all events
     W    -  pathname of widget receiving the event        all events
     X    -  horizontal position   absolute buttonpress, buttonrelease, 
                                             keypress, keyrelease, motion
     Y    -  vertical position     absolute buttonpress, buttonrelease, 
                                             keypress, keyrelease, motion

<event qualifiers>
but := parent("button","Click me to beep; Option-click to beep twice; try Command-Option-click."); 
but("side") := "top";
but{"ButtonRelease-1"} := Tk.beeper;
but{"Option-ButtonRelease-1"} := lambda(); Tk.beeper(); Tk.beeper(); end lambda;
but{"Command-Option-ButtonRelease-1"} := 
		lambda(); for j in [1..4] loop Tk.beeper(); end loop; end lambda;

<HELP>
Button- and keypress-related descriptors can further be qualified by attaching 'modifier' prefixes and 'detail' suffixes, separated from the main descriptor keyword by dashes. 'Detail' suffixes specify a keysymbol for keypress events and button numbers for button events. Thus we can have Keypress-a, Keyrelease-Z, Buttonpress-1 (mousedown with first button), etc. The system allows for up to 5 mouse buttons. 'Modifier' prefixes define keys or buttons that must have been pressed for a modified event to occur, and are also used in a few other special situations. The available modifier prefixes are

    Control             - control key must be down
    Shift               - shift key must be down
    Lock                - shift lock must be down
    Command             - command (Apple) key must be down (Macintosh only)
    Mod1 thru Meta 5    - specified one of 5 special keys must be down 
                            (mapped in system-dependent fashion)
    B1 thru B5          - designated button must be down
    Double              - event must occur twice rapidly, (e.g 'doubleclick')
    Triple              - event must occur three times rapidly, (e.g 'tripleclick')
    Meta                - Key Modj regarded as 'system meta-key' must be down
    Alt                 - Key Modj regarded as 'system alt-key' must be down

Use of such prefixes (and of 'detail' suffixes if desired)  gives us modified event descriptors like B1-motion (drag with first mouse button down), Command-a, Double-Buttonrelease-1 (doubleclick with button 1), etc.  

Modifier prefixes, but not detail suffixes, can be repeated, in lists separated by the '-' character. This gives us such still more closely specified events as Command-Shift-B1-motion (drag with first mouse button and two additonal keys down), Double-B1-Buttonrelease-1 (doubleclick with button 1 while holding first mouse button down), etc.

<arc>
ca := parent("canvas","200,200"); ca("side") := "top";		-- the arc needs a canvas
ark := ca("arc","10,10,50,50"); ark("start,extent,fill") := "0,90,red";
ark2 := ca("arc","110,10,150,50"); ark2("start,extent,style") := "0,150,chord";
ark3 := ca("arc","10,110,50,150"); ark3("start,extent,style") := "0,190,arc";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For arcs, these are the left, top, right, bottom of the enclosing rectangle of the oval on which the arc lies.

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of an arc are:
		style				- pieslice, chord, or arc (circular boundary only)
		start				- starting angle of circular arc, in degrees
		extent				- extent of circular arc, in degrees
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior
		outlinestipple		- pattern for outline

<bitmap>
bitmaps := [["error", "hourglass", "info", "questhead"], ["question", "warning", "gray50", "gray12"]];

for j in [1..2], k in [1..4] loop
	canv_jk := parent("canvas","30,30"); canv_jk("row,column") := [j,k];
	bm_jk := canv_jk("bitmap","15,15");		-- the second parameter is the bitmap anchor point
	bm_jk("bitmap,anchor,foreground,background") := bitmaps(j)(k) + ",center,blue,yellow";
end loop;

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For bitmaps these are the x and y coordinates of the bitmap's anchor point (e.g. center.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a bitmap are:
		bitmap				- file name or built-in bitmap name defining picture geometry
		anchor				- point from which position is reckoned: center,n,s,e,w,nw,sw,ne, or se
		background			- display color for bitmap background
		foreground			- display color for bitmap foreground

Built-in bitmaps with the following names are provided by the SETL interface:

	error, hourglass, info, questhead, question, warning, gray50, gray12 

<line>
ca := parent("canvas","200,100"); ca("side") := "top";
line := ca("line","140,20,180,20,180,40,20,40"); line("arrow,fill,smooth") := "both,blue,true";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For lines (open curves) these are the x and y coordinates of the controlling vertices (note that 'lines' can be splines.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a line (open curve) are:
		width				- line width
		smooth				- if true, line is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- line color
		stipple				- line pattern
		joinstyle			- line corner join style: bevel, miter, or round
		capstyle			- line end style: butt, projecting, or round		
		arrow				- should arrowheads be drawn: none, first, last, or both
		arrowshape			- tuple [overall length, length from point to line end, width]	
<oval>
ca := parent("canvas","200,100"); ca("side") := "top";
oval := ca("oval","80,20,120,40"); oval("width,stipple") := "5,gray12";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For ovals these are the left, top, right, bottom of the enclosing rectangle.

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of an oval are:
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior

<rectangle>
ca := parent("canvas","200,100"); ca("side") := "top";
rect := ca("rectangle","20,20,200,200"); rect("width,fill,outline") := "10,red,blue";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For rectangles these are its left, top, right, and bottom.

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a rectangle are:
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior

<polygon>
ca := parent("canvas","200,200"); ca("side") := "top";
poly := ca("polygon","40,60,180,60,180,100,30,30,20,150"); 
poly("fill,smooth,width,outline") := "yellow,true,3,red";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For polygons (closed curves) these are the x and y coordinates of the controlling vertices (note that 'polygons' can be splines.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a polygon (closed curve) are:
		width				- polygon outline width
		smooth				- if true, polygon is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- color for polygon interior
		outline				- color for polygon outline
		stipple				- pattern for arc interior

<canvastext>
ca := parent("canvas","400,200"); ca("side") := "top";
ct := ca("text","Red text in the canvas"); 
ct("coords") := "30,30"; ct("anchor,font,fill") := "nw,{Times 36},red";	
ct2 := ca("text","Blue text in the canvas"); 
ct2("coords") := "130,40"; ct2("anchor,font,fill") := "center,{Times 36},blue";	

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For canvas text items these are the x and y coordinates of the text rectangle's anchor point (e.g. center.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a canvas text item are:
		text				- actual text string
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		font				- text font, e.g. "Times,20,bold"
		justify				- left, right, or center
		fill				- text color
		stipple				- text pattern
		width				- text area width 

<image>
ca := parent("canvas","400,200"); ca("side") := "top";
abs_img := Tk("image","orchidbig.GIF");			-- read an absolute image
img := ca("image",abs_img); 			-- use the absolute image in a first canvas image
img("coords") := "30,30"; img("anchor") := "nw";	

<HELP>
'Image' objects of two kinds are used in the SETL widget system. 'Absolute' images are data files of images that can be drawn, but may not yet have been drawn. 'Canvas' images are absolute images that have been placed in a canvas, and therefore drawn.

Absolute image objects can be read from files using commands of the form

	img := tkw_name("image",file_name);

where 'tkw_name' is the name of the master widget object. They can also be created by 'photographing' part of a canvas using  commands of the form

	img := canvas_name.image_of([l,t,r,b]).
		
Finally, they can be created from 'image library' images using commands of the form 

	img := tkw_name("image",img_library_object);

The attributes of an absolute image item are:
		file				- source file containing image data
		data				- alternative to 'file': image data as base64 string
		height, width		- height and width of image
		format				- data format for file or data string, e.g. GIF, PPM, PGM
		palette				- image color palette
		channel				- open channel or socket from which to get image data
		
<canvasimage>
ca := parent("canvas","400,200"); ca("side") := "top";
abs_img := Tk("image","orchidbig.GIF");			-- read an absolute image
img := ca("image",abs_img); 			-- use the absolute image in a first canvas image
img("coords") := "30,30"; img("anchor") := "nw";	

<HELP>
'Image' objects of two kinds are used in the SETL widget system. 'Absolute' images are in effect data files of images that can be drawn, but may not yet have been drawn. 'Canvas' images are absolute images that have been placed in a canvas, and therefore drawn. So canvas images (but not absolute images), are like the other canvas items that can be drawn in the rectangle occupied by a canvas, i.e. rectangle, arc, bitmap, image, line, oval, polygon, text, and canvas image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For canvas images these are the x and y coordinates of the images's anchor point (e.g. center.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a canvas image item are:
		image				- image object to appear in canvas item
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se

<canvaswidget>
ca := parent("canvas","400,200"); ca("side") := "top";
ovall := ca("oval","10,10,100,150"); ovall("fill") := "red";

but := parent("button","This button will be put directly into the Canvas"); 
but_incanv := ca("widget",but); but_incanv("coords,anchor") := "30,30;nw";

parent2 := Tk("frame","100,50");		-- this frame will be put directly into the Canvas
parent2_incanv := ca("widget",parent2); parent2_incanv("coords,anchor") := "50,40;nw";

lb := parent2("listbox",3); lb("side") := "left";	-- listbox shows 3 elements
lb(1..0) := "Item1 Item2 Item3 Item4 Item5 Item6 Item7 Item8 Item9 Item10";
				-- listbox contains 10 elements, so a scrollbar is attached
lb("yscroller") := scroller := parent2("scrollbar","v,10"); -- attach a scrollbar
lb("width") := 8; 

scroller("side,fill") := "left,y";		-- make the scrollbar visible

ovall2 := ca("oval","40,10,130,150"); ovall2("fill") := "blue";

<HELP>
Widgets of any other kind can be drawn to canvases, so that canvases can be structured as collages of basic geometric abjects and subcanvases. The position of such a 'canvas widget' is defined by its "coords" attribute, which are the x and y coordinates of the images's anchor point (e.g. center.)

The two attributes of a canvas widget are:
		widget				- widget object to appear in canvas item
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		
Note that canvas widgets are drawn above othe kinds of canvas items.
<tag>
**

<HELP>
********* help text*********

<visual>
**

<HELP>
********* help text*********

<title>
toplevel(OM) := "title_for_my_window";

<HELP>
The title of a toplevel widow is set simply by assigning to its 'OM' attribute, e.g.

		toplevel(OM) := "title_for_my_window";


<cursor>
parent("cursor") := "bogosity"; parent2("cursor") := "iron_cross";

<HELP>
Built-in cursors with the following names are provided:

Arrow cursors:
	arrow, double_arrow, based_arrow_down, based_arrow_up, 
	draft_large, draft_small, top_left_arrow, right_ptr, 
	center_ptr, right_side, left_side, bottom_side, top_side,
	center_ptr, sh_h_double_arrow, sh_v_double_arrow, 
	sh_left_arrow, sh_right_arrow, sh_up_arrow, sh_down_arrow

Cross cursors:
	xterm, x_cursor, plus, tcross, crosshair, spider, fleur, 
	iron_cross, diamond_cross, cross_reverse, cross

T and angle cursors:
	right_tee, left_tee, bottom_tee, top_tee, ll_angle, 
	lr_angle, ul_angle, ur_angle,

Corner cursors:
	bottom_left_corner, bottom_right_corner, top_left_corner, 
	top_right_corner, 

Box cursors:
	dotbox, draped_box, sizing, middlebutton, rightbutton, 
	leftbutton, target, box_spiral,

Miscellaneous cursors:
	 dot, icon, rtl_logo, exchange, mouse, spraycan, pencil, 
	 star, boat, bogosity, pirate, man, question_arrow, 
	 gobbler, gumby, hand1, hand2, heart, trek, clock, circle, 
	 coffee_mug, sailboat, umbrella, watch, shuttle

<fonts>
Tk("font","my_favorite_font,family,size,slant") := "Sabon,18,roman";
Tk("font","a_hateful_font,family,size,slant") := "{Arial Black},36,italic";
mes := parent("message","Hello World"); mes("side") := "top";
mes("font") := "{my_favorite_font}";
mes2 := parent("message","Hello World"); mes2("side") := "top";
mes2("font") := "{a_hateful_font}";
print(Tk("definedFonts"));
print(Tk.font_metrics("{Times}"));
print(Tk.measure_fonted("Now is the time","{Times 24}"));

<HELP>
Fonts are ordinarily indicated in the style illustrated by {Sabon 24 {bold italic}} or 
{{Zapf Dingbats} 24 {bold underline}}. The available font attributes, set by these designators, are 
family (e.g. Sabon or {Zapf Dingbats}), size, weight ('bold' or 'normal'), slant ('roman' or 'italic'), underline ('true' or 'false'), overstrike ('true' or 'false').

A level of indirection, facilitating font substitution where desired, is available through the use of defined fonts. To define a font and set its attributes, we write 

		Tk("font","new_name,attributes") := attribute_vals;

where 'attributes' is a comma-separated list of attribute names, and 'attribute_vals' is a list of corresponding values. An example is

		Tk("font","my_favorite_font,family,size,weight") := "Sabon,18,roman"

Font names introduced in this way can be used in the place of ordinary fonts, e.g. given a message object 'mes' we can write 

		mes("font") := my_favorite_font;

The expression Tk("fonts") returns a list of all the currently available fonts (not including the defined fonts.) The expression Tk("definedFonts") returns a list of all the currently defined fonts.
Tk.font_metrics(font) returns basic metric information about a font, as a map from the attribute names "fixed", "linespace", "ascent", "descent" to their integer values. The 'font' parameter should be supplied in the form illustrated by "{Zapf Dingbats}". Tk.measure_fonted(stg,font) returns the pixel width of the string 'stg' when set in the font 'font' (ignoring the special effects of tabs and linebreaks.)
<grab>
win := TK("toplevel","10,10"); win(OM) := "You must click this button";
but := win("button","Click Here or Die!"); but("side") := "top";
but{OM} := cleargrab(win);
win("grab") := "global";

procedure cleargrab(win); 
	return lambda(); win("grab") := OM; end lambda; 
end cleargrab;

<HELP>
The operation window("grab") := "global" (or OM, or anything else) can be used to set a toplevel window of the SETL interface into a 'modal' stte in which user interaction with other windows is restricted or suppressed. Setting window("grab") := "global" suppresses all interactions with other windows. window("grab") := OM clears the grab. Any other grab value suppresses interactions with other interface windows, but not with other applications.
<update>
Tk.update();
<HELP>
A SETL routine R running after being called in consequence of an initial interface-related event (even an interface timer event) can call the routines of the tkw package to request display and other graphic services, but ordinarily these will not be posted (become visible) in the interface until R completes. To ensure that such graphic changes become visible immediately, the procedure 'Tk.update()' should be called immediately after the calls defining the desired graphic changes. 

<SECTION=Libs>
<events>
	use eventpak;

<HELP>
The SETL eventpak provides basic facilities for connecting SETL to sources of events. One such source of events is the SETL graphic interface itself, but since this can be used directly via its 'tk.mainloop()' call, it does not require eventpak use. However, the eventpak should be used if the SETL graphic interface is to be used with other event sources, for example a voice recognizer.

The eventpak allows single events to be obtained from event sources which return them, and also proivdes event loop objects set up to manage continuing streams of events. Event sources are represented to the eventpak by evt_source_fn objects; These are SETL wrappers around native function objects. Each native event generating package must provide a parameterless function which can be called to obtain such an evt_source_fn object representing its own event stream. For example, the primary graphic interface package Tk.stl provides the function tk_get_event_source_function() for this purpose, and voicepak provides voicepak_get_event_source_function().

To use the eventpak, we first create an event-loop object, and then add event sources to it. Each of these is represented by its evt_source_fn object. A SETL callback fuction is assigned to each such event sourcewhen it is added to the event-loop object. Thes can be removed from the event-loop object when an event stream is to be ignored. Once this has been done, one enters the 'event_mainloop' to get a continuing stream of callbacks, or calls 'event_single' to get a single callback if any is available.

eventpak provides the following routines:

procedure event_create();
		-- create and return an event-loop object
		-- this is the 'evt_inst' appearing in the following calls

procedure event_source_add(evt_inst, evt_source_fn, callback);
		-- register an event source with the 'evt_inst' object; 
		-- this is represented by the evt_source_fn obtained 
		-- from the corresponding native package
		-- it returns an event-source id integer 
		-- which identifies the new event source, for removal if desired

procedure event_remove(evt_inst, evt_id);
		-- remove an event source from the list of registered sources
			
procedure event_mainloop(evt_inst);
		-- enter the main loop, which loops endlessly through the 
		-- list of all registered event sources to handle their events

procedure event_single(evt_inst);
		-- execute a single event; this allows a less efficient but more
		-- flexible event main loop to be programmmed in SETL

<voice recog.>
	use voicepak;

	voicepak_create(string, callback := OM);	-- create a voice recognition object
	voicepak_start_recognize(vp_instance);		-- start voice recognition
	voice_event_source := voicepak_get_event_source_function();
				-- function to be added to an eventpak loop object 

<HELP>
The SETL voicepak allows SETL use of native voice recognition facilities. To use it, one first creates a voice recognition object, and then starts it (it can be suspended subsequently, if desired.) When the voice recognition object is created, a comma-delimited list of phrases to be reconized and returned is passed to it; when any of these phrases is subsequently recognized, an event package consisting of the corresponing string is generated and passed to whatever voice-callback handler has been set up. 

An evt_source_fn object representing the stream of interpreted voice events can be obtained from voicepak and added to an eventpak event-loop object, along with a one-parameter SETL callback-handler routine for these voice events. Detected voice events always generate event package consisting of the character string that was spoken.

voicepak provides the following routines:

procedure voicepak_create(string, callback);	
	-- create a voice recognition object. The 'string' parameter
	-- is a comma-delimited list of phrases to be reconized and returned.
	-- (The Apple voice recognizer does better with long than with
	-- short phrases.) 
	-- voicepak_create returns a vp_instance object to be used in other
	-- calls. If 'callback' is non-OM, it should be a 1-parameter
	-- function, will be called whenever a voice event is detected. 
	-- This is safe only if the voice recognition system
	-- is the only source of asynchronous callbacks. 
	-- Otherwise this callback parameter should be OM, and 
	-- the callback should instead be installed in an event_pak loop object. 
				
procedure voicepak_start_recognize(vp_instance);
				-- start voice recognition

procedure voicepak_stop_recognize(vp_instance);
				-- stop voice recognition
procedure voicepak_idle();
				-- wait for a voice event
procedure voicepak_next_command();
				-- get the next available voice command

procedure voicepak_get_event_source_function();
	-- get the event source function for this package; this is the function 
	-- that must be used in the event package, if that is used

<random>
use random_pak;

handle:= start_random(["A","B","C"], OM);
print([random(handle): n in [1..10]]);
		-- print randomized sequence of 10 letters
print([random(handle): n in [1..10]]);		-- and another such

<HELP>
random_pak provides the two procedures
 
start_random(source,seed);
		-- returns a 'handle', representing a stream of random items

Random(Handle);		-- get next item in a stream of random items

The 'source' in a 'start_random' call can be any of:

1.  An integer n.  The stream consists of integers from 1 to n.
2.  A positive real x.  The stream consists of reals from 0.0 to x.
3.  A set s. The stream consists of random elements of s.
4.  A tuple t. The stream consists of random elements of t.

The 'seed' can be any integer, or OM;  if it is OM the time is used
to generate a starting integer. Use an integer if you want your random selections to be repeatable.

<string_util>
tup_of_tups := breakup(breakup("Jack and Jill;Hot and Cold;Red, White, and Blue",";"),", ");
print(tup_of_tups);
<HELP>
string_utility_pak provides a small library of frequently used string operations in high efficiency native versions. These are:

breakup(obj,chars);		-- cuts a string at any of the indicated characters; 
						-- recursively applicable to tuples of strings
single_out(obj,chars);	-- cuts a string at any of the indicated characters, keeping
						-- them as singletons; 
						-- recursively applicable to tuples of strings
segregate(obj,chars);	-- cuts a string into segments consisting alternately
						-- of characters in/notin 'chars'
						-- recursively applicable to tuples of strings

join(tuple,chars);		-- joins tuple of strings into a string, insterting the string
						-- 'chars' as a separator.

suppress_chars(string,chars);	-- suppress all characters in 'chars', 
								-- returning string of others
keep_chars(string,chars);   	-- keep and return all characters of 'string' 
								-- that belong to 'chars', suppressing others

case_change(string,mode);   	-- change case from upper to lower ofr vide versa,
								-- depending on 'mode', which can be "ul" or "lu"
<red_string_util>
**
<HELP>
red_string_utility_pak extends string_utility_pak with a collection of useful but less frequently used string operations, implemented in SETL; and with a collection of closures which emulates some of SNOBOL's backtracking string-matching capabilities. The operations provided are:

<rx>
**

<HELP>
'rx' is a SETL interface to the native GNU regular expression package; 'rxp' is a SETL class, built on rx and designed to ease its use. The procedures in rx are:

regcomp(rw rx,pattern,flags);
	-- sets rx to the compiled form of the regular expression 'pattern' and returns 0 or an error code
	-- 'flags' is an integer whose bits allow for various special options documented in the rx package. 
regexec(rx,stg,flags,rw pos);	-- runs complied the rx against stg, returning 0 or an error code
	-- if the match succeeds, pos is returned as a tuple defining the way 
	-- in which the whole expression and its subparts were matched. 
	-- 'flags' is an integer whose bits allow for various special options documented in the rx package. 

The operations provided by the class 'rxp' are:

<parser>
**

<HELP>
The native package 'parser' provides just one function:

parse(stg);		-- returns a representation of the parse tree of stg as a SETL tuple.
  				-- stg can be any SETL expression, loop body, procedure, list of such,
  				-- package body,or class body.
<stringm>
**

<HELP>
********helptext********

<get_lines>
**

<HELP>
get_lines_pak provides 4 utility input routies and one print utility:

get_lines(file_name);   -- gets all lines in a file, as a tuple of strings
get_file(file_name); 	-- gets an entire file, as one big string
print_set(the_set);
    -- prints tuples and sets element by element, with indentation

read_lines(file_name);  -- reads succession of lines in SETL or line format

read_named_data(name_of_source_file);
-- reads sections of data and lines, named by preceding headers of the form
-- DATA_FOR_data_item_name and DATA_FOR_LINES_data_item_name

<tk>
**

<HELP>
********helptext********
<numerical>
**

<HELP>
********helptext********
<image>
**

<HELP>
********helptext********
<database>
**

<HELP>
********helptext********
<polynomial>
**

<HELP>
********helptext********
<primes>
**

<HELP>
********helptext********
<concordance>
**

<HELP>
********helptext********
<midi>
**

<HELP>
********helptext********
<IDE_pak>
-- see Tools:writing_a_tool for explanation of the way in which IDE_pak is used.

<HELP>The primitives available via the native package IDE_pak are:

get_buffer();	-- reads the contents of the target edit window of a drag-and-drop operation
get_position();	-- reads the drop position, within a target edit window, of a drag-and-drop operation
get_length();	-- gets length, in characters, of the target edit window of a drag-and-drop operation
set_buffer(from_pos,to_pos,stg);	
	-- replaces indicated section of target edit window contents by indicated string

get_parameter();	-- reads the help-file text section immediately following the tool tag 

get_selection();	-- returns the boundaries of the currently
					-- selected part of the target edit window, as a pair
set_selection(from_pos,to_pos);		-- sets the selection boundaries in the target edit window

<IDE_tools_pak>
-- see Tools:writing_a_tool for explanation of the way in which IDE_pak and IDE_tools_pak are used.

<HELP>IDE_tools_pak provides a set of utility extensions of the native package IDE_pak. The operations it provides are:

<SECTION=Tools>
<using_tools>
use IDE_pak,IDE_tools_pak;		-- other packages can also be used
<HELP>
The tools in this extensible collection are used by dragging them onto an IDE edit window, whose contents they then access, analyze, and (possibly) modify. Some of the tools apply to an entire window or to a preselected part of the window, and so can be dropped anywhere in the window. Others react in a more specific, local manner to the window position at which they are dropped.

Some of the tools provided are:

count_words:		prints list of words appearing in the selected window section, or the whole window

rare: 				prints list of words appearing just once or twice in the selected window section

capitalize: 		capitalizes the selected window section

lower:				un-capitalizes the selected window section

trace: 				inserts code following a procedure header which prints
					parameter values whenever the procedure is called.

show_entries: 		inserts code following a procedure header which 
					displays parameter values in a TK window whenever 
					the procedure is called.

parse: 				parses the selected section of the window, printing an error diagnostic or "OK"

profile: 			after the code in an edit window has  been executed 
					with the "Profiler Dump" and "Debug to File' options  
					both set, this tool will display an execution-time 
					profile of the window, keyed to its source text

debug_setup: 		sets up a program for line-trace debugging and 
					postmortem assertion checking by inserting tracing code

cleanup: 			removes the insertions made by the debug_setup tool

Personal1, etc.		If you supply a program called Personal1, it 
					will be executed when this tag is dragged into an
					edit window, and can acess and modify the window.

<writing_a_tool>
use IDE_pak,IDE_tools_pak;		-- other packages can also be used
<HELP>
IDE 'tools' are SETL programs, executed while SETL programs are being edited, which can access, analyze, and modify the contents of IDE edit windows. The primitives available for this are described by the 'IDE_pak' item of the 'libs' tab in this help window.  Each 'tool' is listed in a help file section of the following form:

	(i)		tool-name 						(within pointed brackets)
	(ii)	tool-parameter-string			can consist of multiple lines
	(iii)	SCRIPT or SCRIPT=program_name	(within pointed brackets)
	(iv)	text of tool program (ignored if SCRIPT=program_name was used) 

Once a tool has  been set up in the format indicated, the tool-parameter-string supplied will be read, and the program P named by 'program_name' will be executed. If the '=program_name' clause has been omitted, then the program text following the SCRIPT tag will be read, compiled into a program P, and executed. (This should be a complete SETL program.)  In either case the tool-parameter-string is available to the program P, as the value of the function 'get_parameter()' supplied by IDE_pak. Note that programs P invoked in this way will normally use IDE_pak, and possibly also the extended set of utility routines available in IDE_tools_pak. 

<count_words>
**
<SCRIPT>
program test;
use ide_pak,extended_SETL_lexer,sort_pak,string_utility_pak,ide_tools_pak;

	buf := get_buffer();
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) = ix2 - ix1 then 		-- trick for 'greater_equal'
		buf := buf(ix1..ix2);
	end if;
	
	print(#(wds := get_tokens(case_change(buf,"ul"))));

	sorted_wds := merge_sort({x: x in wds | #x > 0 and not (x(1) in 
				" 0123456789#:=,./?;'[]=-)(*&^%$#@!~`\n\t\r\"\\|{}+\x3E\x3C") 
							and not x in SETL_reserved_words});
	for x in sorted_wds loop nprint(x ," "); end loop;

end test;
<HELP>
Dropping this on a code window prints the total number of words in the selected section of the window (ignoring comments), along with an alphabetized list of all these words. If nothing has been selected, the whole window is processed.

<rare>
**
<SCRIPT>
program test;
use ide_pak,extended_SETL_lexer,sort_pak,string_utility_pak,ide_tools_pak;

	buf := get_buffer();
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) = ix2 - ix1 then 		-- trick for 'greater_equal'
		buf := buf(ix1..ix2);
	end if;
	
	wds := get_tokens(case_change(buf,"ul"));
	wds := [x: x in wds | #x > 0 and not (x(1) in 
				" 0123456789#:=,./?;'[]=-)(*&^%$#@!~`\n\t\r\"\\|{}+\x3E\x3C") 
							and not x in SETL_reserved_words];
	numoccs := {};
	for x in wds loop numoccs(x) := (numoccs(x)?0) + 1; end loop;
	
	sorted_wds := merge_sort({x: x in wds | #x /= 0 and not (x(1) in "0123456789") and numoccs(x) = 1 
				and x notin SETL_reserved_words and x notin tk_atts});
	sorted_wds2 := merge_sort({x: x in wds | #x /= 0 and not (x(1) in "0123456789") and numoccs(x) = 2 
				and x notin SETL_reserved_words and x notin tk_atts});

	if #sorted_wds /= 0 then 
		sorted_wds := join(sorted_wds," ");
		print("Words occuring once: ",sorted_wds);
	end if;
	
	if #sorted_wds2 /= 0 then 
		sorted_wds2 := join(sorted_wds2," ");
		print("\nWords occuring twice: ",sorted_wds2);
	end if;

end test;
<HELP>
Dropping this on a code window prints a report on all words occuring just once or twice in the selected section of the window. If nothing has been selected, the whole window is processed.

<capitalize>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) /= (ix2 - ix1) then [ix1,ix2] := [1,get_length()]; end if;
	buffer_part := get_buffer()(ix1..ix2);
	set_buffer(ix1,ix2,case_change(buffer_part,"lu"));
end test;
<HELP>
Dropping this on a code window capitalizes the selected section of the window.

<lower>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) /= (ix2 - ix1) then [ix1,ix2] := [1,get_length()]; end if;
	buffer_part := get_buffer()(ix1..ix2);
	set_buffer(ix1,ix2,case_change(buffer_part,"ul"));
end test;
<HELP>
Dropping this on a code window changes the selected section of the window to lower case. If nothing has been selected, the whole window is processed.
<trace>
**
<SCRIPT>
program test;
use ide_pak,ide_tools_pak,string_utility_pak,red_string_utility_pak;
	
	[procname,arglist,eol_loc] := getproc_name_args_linened();

	line_to_insert := "\rprint(\"**Entry to " + procname + ": \",";
	
	for arg in arglist loop line_to_insert +:= ("\" " + arg + " := \"," + arg + ","); end loop;
	line_to_insert := line_to_insert(1..#line_to_insert - 1) + ");";

	set_buffer(eol_loc,eol_loc - 1,line_to_insert);		-- insert the trace line just before the eol
	
end test;
<HELP>
Dropping this on a procedure header inserts code which prints a report on parameter values whenever the procedure is called.

<show_entries>
**
<SCRIPT>
program test;
use ide_pak,ide_tools_pak,string_utility_pak,red_string_utility_pak;
	
	[procname,arglist,eol_loc] := getproc_name_args_linened();
	lines_to_insert := make_code(procname,arglist);
	set_buffer(eol_loc,eol_loc - 1,lines_to_insert);		-- insert the trace line just before the eol

end test;
<HELP>
Dropping this on a procedure header inserts code which displays the parameter values in a TK window whenever the procedure is called. For this facility is used, the procedure being traced should be called from within a main routine invoked by a Tk event,  possibly a timed event. The following example ilustrates the overall structure that can be used.

program test;	-- test of show_entries tool
	use tkw;		-- use the main widget class

	Tk := tkw(); Tk(OM) := "Caption";	
	
	Tk.createtimer(10,main);	-- start the main program after 1/100 sec.

	Tk.mainloop();		-- enter the Tk main loop
	
	procedure main(ntimes);	
		-- main program, representing a non-interactive SETL run
		-- all other code is called starting from here 
	end main;

end test;
<parse>
**
<SCRIPT>
program test;
use ide_pak,parser;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) = (ix2 - ix1) then 
		buffer_part := get_buffer()(ix1..ix2);
		print(if parse(buffer_part) /= OM then "OK" else "error" end if);
	end if;
end test;
<HELP>
Dropping this on a code window parses the selected section of the window.
If the section contains no parse errors, the message "OK' is printed.
Otherwise an error diagnostic is printed.
 
<profile>
**
<SCRIPT>
program test;			-- test program for display of trace data
	use IDE_pak,IDE_tools_pak;
	
	stg := get_buffer();
	file_handle := open("junk","TEXT-OUT");
	printa(file_handle,stg);
	close(file_handle);
	
	while stg /= "" loop

		span(stg,"\t\r \n");	-- skip whitespace
		ma := match(stg,"--");

		if ma /= "" then continue; end if;		-- ship comments
	
		ma := match(stg,"program");

		if ma = "" then 
			print("**** CANNOT FIND NAME OF PROGRAM ****"); stop; 
		else
			span(stg,"\t\r \n");	-- skip whitespace
			uname := break(stg,"\t\r \n(;");
			exit;
		end if;

	end loop;

--	compile_and_run("untitled1.stl");			-- this primitive would be better
--	display_trace("test,untitled1.stl","setl2.dbg"); 		-- display trace of specified units from specified file
	display_trace(uname + ",junk","setl2.dbg"); 	-- display trace of target program

end test;
<HELP>
If the code in an edit window has just been executed with the "Profiler Dump" and "Debug to File' options both set, then dropping this tag on the window will display an execution-time profile of the window, keyed to its source text.

<debug_setup>
parameter
<SCRIPT>
program test;
	use IDE_tools_pak;		-- 
	
	setup_debug(); 		-- set up the debug insertions
end test;

<HELP>
This tool sets up a program for line-trace debugging and postmortem assertion checking by inserting numbered trace-lines into it.

<cleanup>
parameter
<SCRIPT>
program test;
	use IDE_tools_pak;		-- 
	cleanup_debug();		-- remove the insertions made by the debug_setup tool
end test;

<HELP>
This tool removes the insertions made by the debug_setup tool.

<Personal1>
parameter
<SCRIPT=Personal1>
<HELP>
The program called Personal1 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal2>
parameter
<SCRIPT=Personal2>
<HELP>
The program called Personal2 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal3>
parameter
<SCRIPT=Personal3>
<HELP>
The program called Personal3 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal4>
parameter
<SCRIPT=Personal4>
<HELP>
The program called Personal4 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<SECTION=Build>
<program>
program X1;
	X;
end X1;
<HELP>

<procedure>

	procedure X1(X);
		X;
	end X1;
<HELP>

<package>
package X1(X);
	procedure X2(X3);
end X1;
package body X1(X);
	procedure X2(X3);
		X;
	end X2;
end X1;
<HELP>

<class>
class X1(X);
	procedure X2;
end X1;
class body X1(X);
	procedure X2;
		X;
	end X2;
end X1;
<HELP>

<X + X>
X + X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X + X)>
(X + X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X - X>
X - X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X - X)>
(X - X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X * X>
X * X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X * X)>
(X * X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X / X>
X / X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X / X)>
(X / X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X ** X>
X ** X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X ** X)>
(X ** X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X mod X>
X mod X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X mod X)>
(X mod X)
<SCRIPT=replace_the_placeholder>
<HELP>

<-X>
-X
<SCRIPT=replace_the_placeholder>
<HELP>

<-(X)>
-(X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X and X>
X and X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X and X)>
(X and X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X or X>
X or X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X or X)>
(X or X)
<SCRIPT=replace_the_placeholder>
<HELP>

<not X>
not X
<SCRIPT=replace_the_placeholder>
<HELP>

<not (X)>
not (X)
<SCRIPT=replace_the_placeholder>
<HELP>

<ifthen;>
if X then
	X;
else
	X;
end if;
<SCRIPT=replace_the_placeholder>
<HELP>

<ifexp>
if X then X else X end if
<SCRIPT=replace_the_placeholder>
<HELP>

<for>
for X loop
	X;
end loop;
<HELP>

<=>
X = X
<SCRIPT=replace_the_placeholder>
<HELP>

<:=>
X := 
<HELP>

<+:=>
X +:= 
<HELP>

<-:=>
X -:= 
<HELP>

<with:=>
X with:= 
<HELP>

<less:=>
X less:= 
<HELP>

<print>
print(X); 
<SCRIPT=replace_the_placeholder>
<HELP>

<(X)>
(X) 
<SCRIPT=replace_the_placeholder>
<HELP>

<,X>
,X 
<HELP>

<;>
; 
<HELP>

<f(X)>
X(X)
<SCRIPT=replace_the_placeholder>
<HELP>

<[x:]>
[X: X]
<SCRIPT=replace_the_placeholder>
<HELP>

<{x:}>
{X: X}
<SCRIPT=replace_the_placeholder>
<HELP>

<forin>
X in X
<SCRIPT=replace_the_placeholder>
<HELP>

<for=>
X = X(X)
<SCRIPT=replace_the_placeholder>
<HELP>

<|>
 | X
<HELP>

<[..]>
[X..X]
<SCRIPT=replace_the_placeholder>
<HELP>

<{..}>
{X..X}
<SCRIPT=replace_the_placeholder>
<HELP>

<exists>
exists X | X
<SCRIPT=replace_the_placeholder>
<HELP>

<forall>
forall X | X
<SCRIPT=replace_the_placeholder>
<HELP>

<vary>
blah
<SCRIPT=replace_the_token>
<HELP>

<test>
blah
<SCRIPT>
program test; 
	use ide_pak; 
	stg := get_buffer(); [lo,hi] := get_selection(); set_buffer(lo,hi,get_parameter()); 
end test;
<HELP>

<END>

--- Obsolete; not used
<show_debug>
parameter
<SCRIPT>
program test;
	use IDE_tools_pak;		-- 
	show_debug();			-- display the debug information collected by executing a program 
							-- after it has been processed by the debug_setup tool
end test;

<HELP>
This tool displays the debug information collected by executing a program after it has been processed by the debug_setup tool, and then immediately executed. It can also remove the insertions made by the debug_setup tool.

<show_data>
parameter
<SCRIPT>
program test;					-- display the debug information collected by executing a program 
								-- after it has been processed by the debug_setup tool
	use IDE_tools_pak,IDE_pak,sort_pak,string_utility_pak;

	[cycle_no,data] := unstr(get_pdata());
	drop_pos := get_position();
	text := get_buffer();
	line_no := #(breakup(text(1..drop_pos),"\r\n"));
	print("line_no: ",line_no," cycle: ",cycle_no(line_no)); 
	for [name,val] in merge_sort(data(line_no)) loop
		print("\t\t",name,":    ",val);
	end loop;
end test;

<HELP>
Once a program has been processed by using the debug_setup tool, then immediately executing the program, and then using the show_debug tool, dropping this tool on any program line will display the values that all variables in the line had immediately after the line was executed.


